提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
现实背景
人们经常使用图来建模交通网络——这些网络的边携带某种流量,其结点充当“交换机”传送不同边缘之间的流量。设想一个高速公路系统:边是公路,结点是交接处;或者设想计算机网络,这里的边是可以携带数据包的链路,而结点是交换机;再比如一个流体网络,其中的边是输送液体的管道,结点是管道的连接处。这种类型的网络模型有几个成分:①边的容量(说明它们最多能承载多少);②源结点——产生流量;③终端结点,可以“吸收”流量;④最后是流量本身,它是通过边传输的。一、问题引入
假设这是一个水流网络系统,想从s点将水输送到t点,有向边代表管道,其权值表示的含义是该管道的最大容量,水通过该管道的流量不能大于容量,否则管道会破裂,除了s和t以外结点称为中间结点,每一个中间结点都满足:流入该中间结点的流量等于流出的流量,中间结点只是转换的作用,没有存储的功能。问:从s到t能输送最多多少的水流量?
二、问题建模
1.Flow Networks
其流量就是一种抽象的实体:在源结点产生,通过边传输,并在终端结点被吸收,我们将这样一种Flow Networks建模为一个 有向图G=(V,E),具有如下特点:
- 边e上的非负数值ce代表的是容量
- V中只有一个源结点s
- V中只有一个终端结点t
- V中除了s和t的结点叫作中间结点。
我们对该Flow Networks进行了三点假设:
- s没有入边,t没有出边
- 每个结点都至少和一条边关联
- 所有的容量值都用整数来表示
2.Defining Flow
定义s-t flow为函数f:把每条边e映射到一个正实数,f(e)的值表示的是e这条边上实际承载的流量。一个f flow必须满足以下两个特性:
- 容量约束:对于E中的每一个e,有0<=f(e)<=ce
- 平衡约束:对于所有的中间结点有
前者代表所有进入结点v的流量,后者代表从v流出的所有流量
一条边上的流量不能超过其容量,一个flow f的值,表示为v(f),其含义是在源结点产生的流量:
三、算法引入
1. Naive Algorithm
这个算法是初步的算法,并不一定能找到最大流,只能是大多数情况下可以找到最大流,但是这种方法很好理解,并且后面的更优的算法都是以此为基础进行优化的,所以我们先介绍这种算法。
在该算法中,我们需要定义一个Residual Graph(余量图)来表示每条管道还能承载的流量 可以用公式理解:
Residual = Capacity - Flow
每条管道上的红色权值代表流量,黑色代表容量
知道了这些概念后就可以操作该算法了。第一步,在原始图上随便用什么遍历方法找到一条从s到t的augmenting path(简单路径)就可以了,假设我们找到了:s->v2->v4->t 这条路径;然后根据短板原理可以知道我们能输送的最大流量是2,如果是3,就会有水管破裂。
所以这条路径的流量最大只能为2,这三条管道对应的余量应该都减去2,就可以画出当前状态下的余量图:
此时有两条边的余量为0,说明这两条管道已经饱和了,不能承受更多的睡了,于是把余量为0的边删除:
这样我们就完成了第一轮循环。接下来也是同样的操作,再找出一条从s到t的简单路径,设定最大流量,算出余量,删去饱和边,直到找不出一条从s到t的简单路径。第二轮循环:
第三轮循环:
第四轮循环已经找不出一条从s到t的路径了,于是算法终止,得到了最终的余量图,用原始图减去余量图就能得到流量图。
根据之前对问题建的模型,可以只看从s流出的流量和就知道了该图的实际流量是5。这个图的最大流量实际上就是5,但是如果选的路径不是上面这样的顺序,比如:一开始找的路径是这样的,确定流量值为3后,得到这样的余量图,并且删除饱和边
第三次循环已经找不到路径了,但是此时图的流量是4,并不是最大流量5。所以这个算法并不能总是找到最优解。
2. Ford-Fulkerson Algorithm
naive algorithm的问题在于一旦选择了bad path后,不能修正,就像上面描述的那样,选到了阻塞流后,就不能找到最大流了。用简单的示意图来表示:
红色的表示是max flow=2 , 紫色的表示block flow=1
我们现在要介绍的Ford-Fulkerson Algorithm 就是在此基础上优化的,假如选到了阻塞流,依然可以修正。我们依然按照之前用naive algorithm算法失败案例的选边顺序来运行Ford-Fulkerson Algorithm。Ford-Fulkerson Algorithm依然保留了原始图,余量图的概念。
这三步和之前的naive algorithm都是一样的,关键在于之后的这一步,就是删除了饱和边之后,Ford-Fulkerson Algorithm增加了一步回流法:画出该流量通路的逆流边,即从t到s的流向。并且这些回流边在下一轮选择路径试仍然可以被选中。
出现这种情况的时候,我们可以通过Merge(合并)操作处理。
第三轮循环就是到了刚才naive algorithm失败的那轮循环,如果没有这些回流边,该算法也会失败。正是有了这些回流边,因此我们才可以继续选择路径。
第三轮循环: 选中 s-> v2 -> v4 -> v1 -> v3 -> t, 并且确定这天路径的流量为1
移除饱和边后,并添加反向路径,然后Merge相应的边,得到了这样的余量图:
此时,找不到从s到t的路径了,于是算法终止。根据建模时的要求,我们可以从流入源结点的流量判定该图的最大流量为5。
因此,我们就用Ford-Fulkerson Algorithm对先前的失败案例进行修正,并得到了正确答案。
四、最坏情况时间复杂度
1. Worst-Case Iteration Complexity
该原始图的MaxFlow为200,很容易观察出来,但是如果用Ford-Fulkerson Algorithm算法,可能会非常慢。 假设一开始选的路径是 s->v1->v2->t,确定流量值为1,然后删除饱和边,画出回流边,得到的余量图是右边的:
Proof:
由于容量的限制,我们知道在图G没有流量值可以超过MaxFlow,并且每一轮循环中,流量值至少增加1,value从0开始增长并且不超过MaxFlow。
每轮循环至少会让Flow Network 的流量增加1,∴ Iterations<= Amount of MaxFlow。
在这个例子中,每一轮循环仅增加1流量,所以,在最坏情况下
Iterations = Amount of MaxFlow
2. Worst-Case Time Complexity
Proof:
假设有向图G中有m条边,n个结点,并且所有的结点都至少有一条相邻边,
∴m >= n/2. ∴我们可以用O(m+n)=O(m)来简化界限值。
由上面的证明可以知道算法最多循环MaxFlow次,该算法还会产生回流边,
∴余量图中最多有2m条边,即:每条边都有一条回流边。
找到一条从源结点到终端结点的路径,我们可以用广度优先算法或者深度优先算法,时间复杂度为O(m+n)=O(m);假设该网络流的MaxFlow为f,
∴ the Worst-case Time Complexity is O(f*m)
五、Edmonds-Karp Algorithm
我们再对Ford-Fulkerson Algorithm的过程总结一下:
- 根据原始图建立余量图,并初始化边的余量
- 如果能找到从源点到结点的简单路径,则进入循环:
a. 在余量图上寻找一条简单路径
b. 根据短板原理,确定该路径上的瓶颈值x
c. 更新余量图:更新边的余量并删除饱和边
d. 增加回流边
时间复杂度:O(f*m) f是MaxFlow m代表边的数量
该算法的缺陷在于:其时间复杂度依赖于最大流量,∴说明Ford-Fulkerson Algorithm可能会很慢,因为现实中的MaxFlow会很大。
在此基础上,就有了Edmonds-Karp Algorithm,该算法不是一种新的算法,它只是Ford-Fulkerson Algorithm的一种特例。它们唯一的区别就在于2-a步:
Edmonds-Karp Algorithm是在余量图上找源点到终点的最短路径
即:将余量图看成无权图,或者说将每条边的权值看为1,寻找无权图中的最短路径。也就是说,在每一轮循环中,依然是O(m)的时间寻找最短路径,该算法证明了循环次数最多为m*n次,m是边的数量,n是结点数量,∴该算法不再依赖于MaxFlow,性能因此才提升了很多。