Dinic - Dinic算法

问题

用Dinic算法(也称为距离标号算法)求网络G=<V,E>G = <V,E>的最大流,GG是单源点、单汇点,边的容量都为正整数的网络。

解法

Dinic算法也是Ford–Fulkerson方法的一种实现,与Edmonds-Karp算法的区别在于增广路径的搜索方式不同。Dinic算法设计了水位图(Level Graph)/距离标号(Distance Label)来对网络进行搜索。

水位图(Level Graph)/距离图(Distance Graph):从网络的源点(ss)出发进行BFS搜索,源点的水位/距离为dist=0dist = 0,每个节点根据BFS搜索到的邻节点的水位/距离在该节点的基础上加11且都相等,即dist(j)=dist(i)+1dist(j) = dist(i) + 1(设节点vjv_j是节点viv_i的BFS搜索的邻节点)。下图演示一个网络的距离图,每个节点上前一个数字为该节点的距离,后一个数字为该节点的下标:

阻塞流(Blocking Flow):增广路径中最小的剩余容量(瓶颈)Δ=min{cf(i,j)}\Delta = min \{ c_f(i,j) \},其中vi,vjv_i, v_j是相邻节点,且水位差满足dist(i)=dist(j)+1dist(i) = dist(j) + 1

Dinic算法的步骤如下:

(1)(1) 初始化所有节点之间的流为00,即f(i,j)=f(j,i)=0f(i,j) = f(j,i) = 0(节点vi,vjv_i, v_j为相邻节点),初始化该网络的最大流为flowmax=0flow_{max} = 0

(2)(2) 通过BFS构建水位图;

(3)(3) 在水位图中寻找一个阻塞流作为增广路径,更新该路径上所有边的剩余容量和最大流:

flowmax=flowmax+Δf(i,j)=f(i,j)+Δf(j,i)=f(j,i)Δcf(i,j)=cf(i,j)Δcf(j,i)=cf(j,i)+Δ\begin{matrix} flow_{max} = flow_{max} + \Delta \\ f(i,j) = f(i,j) + \Delta \\ f(j,i) = f(j,i) - \Delta \\ c_f(i,j) = c_f(i,j) - \Delta \\ c_f(j,i) = c_f(j,i) + \Delta \end{matrix}

具体寻找阻塞流的方法,和Edmonds-Karp算法类似,从源点ss开始BFS搜索,并通过队列queuequeue存储所有待搜索节点,从队列取出头节点viv_i,遍历其所有邻节点vjv_j,将满足cf(i,j)>0c_f(i,j) \gt 0dist(i)=dist(j)+1dist(i) = dist(j) + 1条件的加入队列queuequeue中,直到找到汇点或队列为空为止。若通过BFS搜索到一条阻塞流,则更新剩余网络和最大流;若无法搜索到阻塞流,则算法结束。

可以看出Dinic算法与Edmonds-Karp算法的核心区别只在于BFS搜索的数据结构不同,Dinic算法用距离标号来限制邻节点的搜索,而Edmonds-Karp除了剩余容量以外没有其他限制。Dinic算法运行在重新构建的水位图上,边的数量比原始的网络少很多,因此搜索的时间复杂度大大降低。

该算法的时间复杂度为O(VElog2V)O(\lvert V \rvert \cdot \lvert E \rvert \cdot log_2 \lvert V \rvert)

Dinic Algorithm

源码

Dinic.h

Dinic.cpp

测试

DinicTest.cpp

Last updated