社区讨论
今晚ABC的G题的最小割问题
学术版参与者 3已保存回复 5
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 5 条
- 当前快照
- 1 份
- 快照标识符
- @lo9a8td2
- 此快照首次捕获于
- 2023/10/28 08:07 2 年前
- 此快照最后确认于
- 2023/10/28 08:07 2 年前
ABC239G
在跑完Dinic算法之后,怎么判断哪些边属于割边呢?
为什么下面的代码里用分层图的
CPPd数组可以判断出来那些点被用到了呢?#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
typedef long long LL;
const int maxn = 205, maxm = 100 * maxn * maxn;
const LL INF = 0x3f3f3f3f3f3f3f3f;
int h[maxn], cur[maxn], e[maxm], ne[maxm], idx;
LL f[maxm];
int d[maxn], q[maxn];
int n, m, S, T;
void add(int a, int b, LL c){
e[idx] = b, f[idx] = c, ne[idx] = h[a], h[a] = idx++;
e[idx] = a, f[idx] = 0, ne[idx] = h[b], h[b] = idx++;
}
bool bfs(){
int hh = 0, tt = -1;
memset(d, -1, sizeof(d));
q[++tt] = S, d[S] = 0, cur[S] = h[S];
while(hh <= tt){
int t = q[hh++];
for(int i = h[t]; ~i; i = ne[i]){
int j = e[i];
if (d[j] == -1 && f[i]){
d[j] = d[t] + 1;
cur[j] = h[j];
if (j == T) return true;
q[++tt] = j;
}
}
}
return false;
}
LL find(int u, LL limit){
if (u == T) return limit;
LL flow = 0;
// start from cur[u] instead of h[u] <- important
for(int i = cur[u]; ~i && flow < limit; i = ne[i]){
int j = e[i];
cur[u] = i;
if (d[j] == d[u] + 1 && f[i]){
LL t = find(j, min(f[i], limit - flow));
if (!t) d[j] = -1;
else f[i] -= t, f[i ^ 1] += t, flow += t;
}
}
return flow;
}
LL dinic(){
LL res = 0, flow;
while(bfs()) while(flow = find(S, INF)) res += flow;
return res;
}
int main(){
#ifdef LOCAL
freopen("data.in","r",stdin);
freopen("data.out","w",stdout);
#endif
memset(h, -1, sizeof h);
scanf("%d%d", &n, &m);
S = n + 1, T = n;
while(m--){
int a, b;
scanf("%d%d", &a, &b);
add(a + n, b, INF), add(b + n, a, INF);
}
int t = idx;
for(int i = 1; i <= n; i++){
int x;
scanf("%d", &x);
if (i != 1 && i != n) add(i, i + n, x);
else add(i, i + n, INF);
}
cout << dinic() << '\n';
vector<int> ans;
for(int i = 1; i <= n; i++)
if (d[i] != -1 && d[i + n] == -1) ans.push_back(i);
cout << ans.size() << '\n';
for(auto u : ans) printf("%d ", u);
putchar('\n');
}
回复
共 5 条回复,欢迎继续交流。
正在加载回复...