最大流及dinic算法
Ford-Fulkerson 增广路算法
通过寻找增广路来更新最大流,有EK,Dinic,SAP,ISAP等算法。
残量网络
对流函数$f$,残量网络$G_f$(Residual Network) 是网络G中所有结点和剩余容量大于0的边构成的子图。
注意:残量网络中包含反向边。
增广路
在原图$G$中,若有一条从源点到汇点的路径的所有边的剩余容量都大于0,则此路为增广路。即残量网络中从源点到汇点的路。
反向边
增广不一定最优,反向边给后续反悔的机会。初始建正边和反边,反边流量为0,在增广时,给反向边加流量。
实现细节
前向星中要记得用成对存(^1 )
EK动能算法
BFS找增广路,增广之。
- 找:即BFS找一条路,注意合法性即可
- 增广:从来的路走一遍,将路上的流量减去,答案加上路上的最小流量。
复杂度$O(nm^2)$(n为点,m为边)
dinic
每次增广前,用BFS将图分层,设源点层数为0,层数即为离源点的距离。
这样的优点是:
- 如果不存在增广路,可以立即停止(即汇点的层数不存在)
- 保证每次增广最短的路。
然后DFS找增广路:
每次都只找比当前点层数多1的点增广,这样就不会绕一圈到一个点上比如不会从第6层到第1层。这里要利用DFS将所有路增广掉。
其复杂度为$O(n^2m)$, 实际使用中可以处理1e4-5的网络,在二分图匹配中,复杂度为$O(m \sqrt n)$
优化
- 多路增广:一次DFS中,增广完还有剩余流量,继续dfs找
- 当前弧:已经增广过的边不会有第二次。
dinic实现
其中当前弧优化部分,每次BFS都刷新一次,每次dfs中不管用没用完都标记,如果有容量可以走也只能等下一轮bfs了。
那些真正没有流量的,一种是自己没流量了,这个在bfs中判断即可。
另一种是后继路径没有流量了,这个在dfs中剪枝,让这个点的deg为0,这只是对这个dfs有效,在下一轮中没有影响。
以下是算法竞赛进阶指南中的带有优化的dinic模版,使用链式前向星存图。
1 |
|