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;
    	}
    }
}
posted @ 2020-11-19 18:00  hyskr  阅读(149)  评论(0编辑  收藏  举报