[Algorithm] Maximum Flow

Ref MIT: lecture-13-incremental-improvement-max-flow-min-cut/

 


 

Ford Fulkerson algorithm for finding maximal flow in a flow network:

  • Keep adding flow through new augmenting paths for as long as it is possible;
  • When there are no more augmenting paths, you have achieved the largest possible flow in the network.

 

Ford Fulkerson最大流算法 (Depth-First)

    -- Aleksandar Ignjatovic version.

左边是Residual flow network,一定要亲自画出来。

(a) 初始状态,通过DFS找一条路径作为augmented path; 可见瓶颈是4,然后得到右图。

【注意,为何这里augmented path的选择是如此方式,是否可以变为最短路径作为更好的选择呢】

(b) 同上。

(c) 同上。

(d) 正向的有权边越来越少;然后画出右图(update后的)的residual flow netowork如下。

      

(e) 这个residual flow netowork貌似已经没有了正向有权边。那么,就可以end了。(d)右就是最终结果,以上是最小割。

 

良心视频 + 个人补充https://www.youtube.com/watch?v=Z8gcjuS0Vb8&t=393s

此处注意标号(s,8)表示上一个节点是s node,(s,8)允许通过的流量是8。

增广链的选择,从t node的标号倒推所得。

此时,最大流等于最小割。

 

Follow an arbitrary path until you reach the sink.

Not guaranteed to terminate.

 

举例演示其繁琐性:

最后一张 右边的1->2 又变回了 初始状态 value=1。

 

让我们抽出两张对比:

可见,中间的这条边value=1成了瓶颈。导致了i++类似缓慢的递归过程。

 

Time complexity

O(KE) K=Maximum Flow, E=Edge

Dependency on the flow

 

 

最大流最小割定理

  Ref: http://www.cnblogs.com/TreeDream/p/5929429.html

  Ref: https://wenku.baidu.com/view/d9c9b9220722192e4536f6e1.html (良心PPT

 

割的净流f = f(2,4)+f(4,3)+f(3,5) = 12+(-4)+11=19   //等于node1的output

割的容量c(2,4)+c(3,5)=12+11=23

 

多一些例子如下:

 

可以计算出对于这两种情况净流f(S,T)仍然等于19。  //等于node1的output

 

割的净流:f = f(2,4)+f(4,3)+f(5,4)+f(5,6) = 12+(-4)+7+4=19   //等于node1的output

 

割的容量:c(2,4)+c(5,4)+c(5,6)=12+7+4=23

 

割的净流:f = f(1,2)+f(3,2)+f(4,3)+f(5,4)+f(5,6) = 11+1+(-4)+7+4=19   //等于node1的output

割的容量:c(1,2)+c(3,2)+c(5,4)+c(5,6)=16+4+7+4=31 (一瞧就不是最小的割)

 

 

对于任意一个割的净流f(S,T)一定是小于等于割的容量C(S,T)。那也即是,对于网络的任意一个流f一定是小于等于任意一个割的容量C(S,T)。

而在所有可能的割中,存在一个容量最小的割,我们称其为最小割。(回流最小)

 

最大流最小割定理 (参考)

对于一个网络流图G=(V,E),其中有源点s和汇点t,那么下面三个条件是等价的:
1. 流f是图G的最大流
2. 残留网络Gf不存在增广路
3. 对于G的某一个割(S,T),此时f = C(S,T)


首先证明1 => 2:

我们利用反证法,假设流f是图G的最大流,但是残留网络中还存在有增广路p,其流量为fp。则我们有流f'=f+fp>f。这与f是最大流产生矛盾。


接着证明2 => 3:

假设残留网络Gf不存在增广路,所以在残留网络Gf中不存在路径从s到达t。
我们定义S集合为:当前残留网络中s能够到达的点。
同时定义T=V-S。//到达不了的点的集合T
此时(S,T)构成一个割(S,T)。且对于任意的u∈S,v∈T,有f(u,v)=c(u,v)。若f(u,v)<c(u,v),则有Gf(u,v)>0,s可以到达v,与v属于T矛盾。
因此有f(S,T)=Σf(u,v)=Σc(u,v)=C(S,T)。


最后证明3 => 1:

由于f的上界为最小割,当f到达割的容量时,显然就已经到达最大值,因此f为最大流。

 


 

Edmonds-Karp求最大流算法 (Breadth-First)

核心思想就是不断找增广路,每找到一条增广路,记录增广路中 边流量最少的值 d

然后在当前找到增广路中

    • 每一条正向弧减去d,
    • 每一条反向弧加上d,

当不再找到增广路的时候,就证明当前的总流量已经是最大流;

至于怎样找增广路。。一致认为BFS是最好的方法了。

 

英伦良心TutorialEdmonds Karp Max Flow Algorithm Tutorial

1. 发现最短路径

Paths:

    • S->1->2
    • S->1->3
    • S->3->4

并顺便记录了每个node的child node。

    • S: 1, 3
    • 1: 2, 3
    • 3: 4
    • 2: t
    • 3: 4
    • 4: 2, t

可见,最短路径只是根据BFS找,并没有什么特殊的。

 

2. 处理最短路径

加了反向边,每一条正向弧减去了15。

Total Flow += 15

 

3. 寻找最短路径(again)

可见,s->3这次也变为了0边。

Total Flow = 15+4, 第二次迭代结果是19.

 

4. 寻找最短路径(again)

2->t, s->3都变为了0边,那么最短路径的选择结果便有了改变。

Total Flow = 19+7, 第二次迭代结果是26.

 

Time complexity 

All vertices in residual graph increase monotonically.

Total number of iterations is O(VE) V=Vertices, E=Edges

Each iteration O(E)

Therefore total runtime O(VE2) 

 


 

Maximum matching in bipartite graphs

二分图最大匹配

 

二分图:简单来说,如果图中点可以被分为两组,并且使得所有边都跨越组的边界,则这就是一个二分图。准确地说:把一个图的顶点划分为两个不相交集 UU 和VV ,使得每一条边都分别连接UU、VV中的顶点。如果存在这样的划分,则此图为一个二分图。二分图的一个等价定义是:不含有「含奇数条边的环」的图。图 1 是一个二分图。为了清晰,我们以后都把它画成图 2 的形式。

匹配:在图论中,一个「匹配」(matching)是一个边的集合,其中任意两条边都没有公共顶点。例如,图 3、图 4 中红色的边就是图 2 的匹配。

Bipartite Graph(1)  Bipartite Graph(2)  Matching  Maximum Matching

我们定义匹配点匹配边未匹配点非匹配边,它们的含义非常显然。例如图 3 中 1、4、5、7 为匹配点,其他顶点为未匹配点;1-5、4-7为匹配边,其他边为非匹配边。

 

最大匹配:一个图所有匹配中,所含匹配边数最多的匹配,称为这个图的最大匹配。图 4 是一个最大匹配,它包含 4 条匹配边。

完美匹配:如果一个图的某个匹配中,所有的顶点都是匹配点,那么它就是一个完美匹配。图 4 是一个完美匹配。显然,完美匹配一定是最大匹配(完美匹配的任何一个点都已经匹配,添加一条新的匹配边一定会与已有的匹配边冲突)。但并非每个图都存在完美匹配。换一个说法:最多有多少互相喜欢的男孩/女孩可以配对儿?这就是最大匹配问题。

 

一、匈牙利算法

求解最大匹配问题的一个算法是匈牙利算法,下面讲的概念都为这个算法服务。

5

交替路:从一个未匹配点出发,依次经过非匹配边、匹配边、非匹配边…形成的路径叫交替路。

增广路:从一个未匹配点出发,走交替路,如果途径另一个未匹配点(出发的点不算),则这条交替路称为增广路(agumenting path)。例如,图 5 中的一条增广路如图 6 所示(图中的匹配点均用红色标出):

6

增广路有一个重要特点:非匹配边比匹配边多一条。因此,研究增广路的意义是改进匹配。只要把增广路中的匹配边和非匹配边的身份交换即可。由于中间的匹配节点不存在其他相连的匹配边,所以这样做不会破坏匹配的性质。交换后,图中的匹配边数目比原来多了 1 条。

我们可以通过不停地找增广路来增加匹配中的匹配边和匹配点。找不到增广路时,达到最大匹配(这是增广路定理)。

那么,如何在某一时刻/状态 找增广路呢?

匈牙利树一般由 BFS 构造(类似于 BFS 树)。从一个未匹配点出发运行 BFS(唯一的限制是,必须走交替路),直到不能再扩展为止。例如,由图 7,可以得到如图 8 的一棵 BFS 树:

7   8    9

这棵树存在一个叶子节点为非匹配点(7 号),但是匈牙利树要求所有叶子节点均为匹配点,因此这不是一棵匈牙利树。

(因为node7,所以不是匈牙利树)

如果原图中根本不含 7 号节点,那么从 2 号节点出发就会得到一棵匈牙利树。这种情况如图 9 所示(顺便说一句,图 8 中根节点 2 到非匹配叶子节点 7 显然是一条增广路,沿这条增广路扩充后将得到一个完美匹配)。

 

匈牙利算法的要点如下

  1. 从左边第 1 个顶点开始,挑选未匹配点进行搜索,寻找增广路

    1. 如果经过一个未匹配点,说明寻找成功。更新路径信息,匹配边数 +1,停止搜索。
    2. 如果一直没有找到增广路,则不再从这个点开始搜索。事实上,此时搜索后会形成一棵匈牙利树(Fig.9)。我们可以永久性地把它从图中删去,而不影响结果。
  2. 由于找到增广路之后需要沿着路径更新匹配,所以我们需要一个结构来记录路径上的点。DFS 版本通过函数调用隐式地使用一个栈,而 BFS 版本使用 prev 数组。

 

过程演示

先从1出发,找增广路,找到1->A 这条路,标记并记录。

从2出发,找到2->B这条路,标记并记录。

从3开始找,发现3所连接边全部被占用,这时进行一个神奇的操作:

    • 从三开始找一条增广路3 -> A -> 1 -> B -> 2 -> C
    • 下划线要出现在两端(增广路的性质)
    • 有增光路,绿线所示

Finally,在图中将有两种颜色的边删去,留下绿色的边。

 

性能比较

两个版本的时间复杂度均为O(VE)。DFS 的优点是思路清晰、代码量少,但是性能不如 BFS。

我测试了两种算法的性能。对于稀疏图,BFS 版本明显快于 DFS 版本;而对于稠密图两者则不相上下。

在完全随机数据 9000 个顶点 4,0000 条边时前者领先后者大约 97.6%,9000 个顶点 100,0000 条边时前者领先后者 8.6%, 而达到 500,0000 条边时 BFS 仅领先 0.85%。

 

二、最大流算法

然而,我们也可以把这个问题当作是最大流问题,如下:(匈牙利算法实际上是对最大流算法的一种改进,提高了效率

中间部分的节点容量设置为1。

计算二分图最大匹配除了匈牙利算法(Hungarian Algorithm),还可以用最大流(Maximal Flow)。

Link: https://www.youtube.com/watch?v=x2BdRml5lmc

Notice:设,所有Edges的权值都是1

 


 

巧妙利用min cuts

 

(1) 实验与仪器,以获得最大受益为目的挑实验来做

E1 (10) --> I1 (5), I2 (6)

E2 (25) --> I2 (6), I3 (7)

因为最大净收益 = 所有实验收益 - 相应实验方案割的容量

所以最大净收益 = 所有实验收益 - 最大流

注意 cut的位置!以下稍作权值调整再做一次练习:

最大净收益(9) = 所有实验收益(20+25) - 最大流(5+6+25)

 

(2) 断开连接,容量代价最小

任务:以最小的断开link的cost分离attacher and victims的PC.

Sol:找到两者的最大流,即是最小割所有正向割边的容量和称为割的容量,那个最小容量的割),断在这些属于min cuts的edge即可。

 

(3) 伤员分配问题

任务:左边building里的伤员需要运送到距离20KM以内的医院。

Sol:左边是building内的伤员数量,右边对应医院的容纳量。 

 

 

(4) 宴席人员分配问题

任务:左边家庭里的成员坐在安排的宴席餐桌,要求家庭成员不能坐在一起。

Sol:添加右边的到T Node的流,权值即是餐桌能容纳的人数。

 

posted @ 2017-06-02 09:16  郝壹贰叁  阅读(817)  评论(0编辑  收藏  举报