Dinic
转:
- 网络流求最大流Dinic 当前弧 + 无用点优化
Dinic算法
- 时间复杂度\(O(n^2m)\),一般1e5规模的都可以跑过去;
- 在EK算法(Edmonds-Karp)中,每次BFS后只找到一条增广路,Dinic算法每次可以找到多条,从而更加优秀
- Dinic算法每次先BFS构造出分层图,再在分层图上Dfs找到增广路,在回溯时更新剩余容量
当前弧优化
- BFS之后每增广一条路,这条路就一定不会再可以到达汇点,下次就不再遍历这条边
- 体现在代码上就是把head拷贝出来,Dfs的时候实时更新就好了
code
int n, m, s = 0, t = n + m + 1, k;
int bfs() {
memset(depth, 0, sizeof(depth)); queue<int> q; q.push(s); depth[s] = 1;
while (q.size()) {
int u = q.front(); q.pop();
for (int i = head[u]; i; i = e[i].next) {
int v = e[i].to;
if (depth[v] || e[i].flow <= 0) continue;
depth[v] = depth[u] + 1;
q.push(v);
if (v == t) return 1;
}
}
return 0;
}
int now[maxn], sum = 0;
int dinic(int x, int lim) {
if (x == t) return lim;
int sum = 0;
for (int i = now[x]; i && lim; now[x] = i, i = e[i].next) {
int v = e[i].to;
if (depth[v] != depth[x] + 1 || e[i].flow <= 0) continue;
int f = dinic(v, min(e[i].flow, lim));
sum += f, lim -= f, e[i].flow -= f, e[i ^ 1].flow += f;
}
if (!sum) depth[x] = 0;
return sum;
}
main() {
while (bfs()) {
memcpy(now, head, sizeof(head));
while (1) {
int cur = dinic(s, inf);
ans += cur;
if (!cur) break;
}
}
}