相比于EK算法,Dinic算法在稀疏图上效率相当(可视n、m相近),而在稠密图上的处理更优秀。
对网络流基本思想不清楚可参见我的另一篇博客《网络流的核心思想》。
分层思想
Dinic算法在每次增广前,先用 BFS 来将图分层。设源点的层数为 0 0 0,那么一个点的层数便是它离源点的最近距离。
通过分层,可起到如下两种效果:
- 如果不存在到汇点的增广路(即汇点的层数不存在),我们即可停止增广。
- 确保我们找到的增广路是最短的(每次找增广路的时候,都只找比当前点层数多 1 1 1的点进行增广)。
两个优化
- 多路增广:在使用EK算法时,由于我们使用BFS找增广路,当每次贪心取得一条增广路并增广后,我们从汇点沿着增广路往前走,很可能会遇见一些点实际经过的流量小于改点所有入度的容量和,或者说在残量网络中,改点的入度和初度均大于 0 0 0,显然我们可以利用该点后向弧的残量向该点前向弧增广。上面的这一过程涉及到回溯的操作,BFS处理这一操作并不方便。而Dinic算法使用DFS找增广路,这就给了我们使用一次DFS找到多条增广路并增广的机会(见代码),大大提高了算法的效率。
- 当前弧优化:显然,由于上述多路增广操作,对于任意节点,我们每增广它的一条前向弧,意味着这条弧后所有边都被我们多路增广过了,那么当我们再次处理该节点时,就可以不用考虑这条弧。或者说,如果一条边已经被增广过,那么它就没有可能被增广第二次。那么,我们下一次进行增广的时候,就可以不必再走那些已经被增广过的边。
时间复杂度
最多仅需 n − 1 n-1 n−1轮增广即可求得最大流,单轮增广的最坏复杂度是 O ( n m ) O(nm) O(nm),总的复杂度为 O ( n 2 m ) O(n^2m) O(n2m),但事实上对于随机图,Dinic的实际运行速度要远由于这一时间上界。
特别地,在求解二分图最大匹配问题时,Dinic 算法的时间复杂度是 O ( m n ) O(m\sqrt n) O(mn