用Bfs查找标号一条到终点的路径,然后用Dfs流。需要注意的是,流完以后不需要立即退出再查找,而是将当前点的流量减去流去的后继续。
#include<cstdio>
#include<algorithm>
using namespace std;
const int inf = 2147483647, N = 1013;
int d[N*N],lis[N*N],y_[N*N*6],v[N*N*6],next[N*N*6],g[N*N];
int ans,n,tot,S,T;
void ins(int i, int j, int z) {
next[++tot] = g[i]; g[i] = tot; y_[tot] = j; v[tot] = z;
next[++tot] = g[j]; g[j] = tot; y_[tot] = i; v[tot] = 0;
}
bool bfs(int r) {
fill(d, d + T + 1, 0);
d[lis[1] = r] = 1;
for (int p1 = 1, q1 = 1; p1 <= q1; ++p1)
for (int p = g[r = lis[p1]]; p; p = next[p])
if (!d[y_[p]] && v[p]) d[lis[++q1] = y_[p]] = d[r] + 1;
return d[T];
}
int dfs(int r, int flow) {
if (r == T) return flow;
int ret = 0;
for (int t,p = g[r]; p && ret < flow; p = next[p])
if (v[p] && d[y_[p]] == d[r] + 1) {
ret += t = dfs(y_[p], min(v[p], flow - ret));
v[p] -= t, v[p ^ 1] += t;
}
if (!ret) d[r] = 0;
return ret;
}
int main() {
tot = 1;
scanf("%d", &n);
S = n * n + n + 1;
T = S + 1;
for (int i = 1,xt; i <= n; ++i)
for (int j = 1; j <= n; ++j) {
scanf("%d", &xt);
ins(S, (i - 1) * n + j, xt);
ins((i - 1) * n + j, n * n + i, inf);
ins((i - 1) * n + j, n * n + j, inf);
ans += xt;
}
for (int i = 1,xt; i <= n; ++i) {
scanf("%d", &xt);
ins(n * n + i, T, xt);
}
while (bfs(S)) ans -= dfs(S, inf);
printf("%d\n", ans);
return 0;
}
995

被折叠的 条评论
为什么被折叠?



