最大流 (Maximum Flow) 之 Ford-Fulkerson

算法 同时被 2 个专栏收录
2 篇文章 0 订阅
2 篇文章 0 订阅

最大流(Maximum Flow)

接上一篇算法笔记(Chapter26)———最大流(Maximum Flow)之流网络和流
一个菜🐔倔强的取经之路。
为了知识的严谨性,本文相关的定义是按照算法导论(第三版) copy and paste。我的理解和总结会适当的添加在这些定义后面用来帮助大家理解。我认为一些重要东西都已经加粗高光标记了。本文算是对这一块内容的学习总结,如有错误欢迎大家指正,交流。

2.Ford-Fulkerson方法

我们称其为"方法"而不是"算法",是因为它包含了几种运行时间各不相同的具体实现。Ford-Fulkerson方法依赖于三种重要思想,它们与许多的流算法有关: 残存网络(Residual networks)增广路径(Augmenting paths)割(Cut)

Ford-Fulkerson方法循环增加流的值,在开始的时候,对于所有的结点 u , v ∈ V u,v \in V u,vV, f ( u , v ) = 0 f(u,v)=0 f(u,v)=0,给出的初始流量值为0。在每一次迭代中,我们将图 G G G 的流的值( ∣ f ∣ |f| f )进行增加,方法就是在一个关联的 “残存网络” G f G_f Gf 中寻找一条 “增广路径”。一旦知道图 G f G_f Gf 中一条增广路径的边,就可以很容易辨别出 G G G 中的一些具体的边,我们可以对这些边上的流量进行修改,从而增加流的值。虽然Ford-Fulkerson方法的每次迭代都增加流的值,但是对于图 G G G 的一条特定边来说,其流量值可能增加,也可能减少,对某些边的流量值进行缩减是必要的,以便让算法可以将更多的流从源结点发送到汇点。重复对流进行这一过程直到残存网络中不再存在增广路径为止最大流最小割定理(Max-flow min-cut) 将证明该过程终结时,将获得一个最大流。

残存网络(Residual networks)

给定流网络 G G G 和流量 f f f,残存网络 G f G_f Gf 由那些仍有空间对流量进行调整的边构成。流网络的一条边可以允许的额外流量等于该边的容量减去该边上的流量。如果该差值为正,则将该条边置于图 G f G_f Gf 中,并将其残存容量设置为 c f ( u , v ) = c ( u , v ) − f ( u , v ) c_f(u,v) = c(u,v)-f(u,v) cf(u,v)=c(u,v)f(u,v)。如果边 ( u , v ) (u,v) (u,v) 的流量等于其容量,则其 c f ( u , v ) = 0 c_f(u,v)=0 cf(u,v)=0,该条边不属于图 G f G_f Gf

残存网络 G f G_f Gf 还可能包含图 G G G 中不存在的边。该方法对流量进行操作的目标是增加总流量(也就是流的值),为此,可能对某些特定边上的流量进行缩减。为了表示对一个正流量 f ( u , v ) f(u,v) f(u,v) 的缩减,我们将边 ( v , u ) (v,u) (v,u) 加入到图 G f G_f Gf 中,并将其残存容量设置为 c f ( v , u ) = f ( u , v ) c_f(v,u)=f(u,v) cf(v,u)=f(u,v)。也就是说一条边所能允许的反向流量最多将其正向流量抵消。残存网络中的这些反向边允许将已经发送出来的流量发送回去。而将流量从同一条边发送回去等同于缩减这条边的流量。

残存容量(Residual capacity)

假设我们有一个流网络 G ( V , E ) G(V,E) G(V,E),其源结点为 s s s,汇点为 t t t,设 f f f 为图 G G G 中的一个流,考虑结点对 u , v ∈ V u,v\in V u,vV定义残存容量 c f ( u , v ) c_f(u,v) cf(u,v)

c f ( u , v ) = { c ( u , v ) − f ( u , v ) i f ( u , v ) ∈ E f ( v , u ) i f ( v , u ) ∈ E 0 o t h e r w i s e c_f(u,v)=\left\{\begin{matrix} c(u,v)-f(u,v) & if(u,v)\in E\\ f(v,u) & if(v,u)\in E\\ 0 & otherwise \end{matrix}\right. cf(u,v)=c(u,v)f(u,v)f(v,u)0if(u,v)Eif(v,u)Eotherwise
因为如果边 ( u , v ) ∈ E (u,v) \in E (u,v)E,那么意味着边 ( v , u ) ∉ E (v,u) \notin E (v,u)/E (上一篇有提到,流网络中不可以出现自循环)。所以对于每一条边来说,上述公式只有一种情况成立

残存网络中的一个流给我们指出的是一条路线图,如何在原来的流网络中增加流。如果 f f f G G G 的一个流, f ′ f' f是对应的残存网络 G f G_f Gf 中的一个流,定义 f ↑ f ′ f \uparrow f' ff 为流 f ′ f' f 对流 f f f 的递增(Augmentation):

( f ↑ f ′ ) ( u , v ) = { f ( u , v ) + f ′ ( u , v ) − f ′ ( v , u ) i f ( u , v ) ∈ E 0 o t h e r w i s e (f \uparrow f')(u,v) =\left\{\begin{matrix} f(u,v)+f'(u,v)-f'(v,u) &if(u,v)\in E \\ 0 & otherwise \end{matrix}\right. (ff)(u,v)={f(u,v)+f(u,v)f(v,u)0if(u,v)Eotherwise

抵消操作(Cancellation)

因为在残存网络中将流量发送到反向边上等同于在原来的网络中缩减流量,所以将边 ( u , v ) (u,v) (u,v) 的流量增加 f ′ ( u , v ) f'(u,v) f(u,v),但减少 f ′ ( v , u ) f'(v,u) f(v,u)。在残存网络中将流量推送回去称为抵消操作。比方说,我要给你10颗糖,你要给我3颗糖,那么可以等价为我给你7颗糖,你不用给我糖。

增广路径(Augmenting paths)

给定流网络 G = ( V , E ) G=(V,E) G=(V,E)和流 f f f, 增广路径 p p p 是残存网络 G f G_f Gf 中一条从源结点 s s s 到汇点 t t t 的简单路径。(=。=换句话来讲其实就是一条从 s s s t t t 的通路。) 对于一条增广路径上的边 ( u , v ) (u,v) (u,v),我们可以增加其流量的幅度最大为 c f ( u , v ) c_f(u,v) cf(u,v) (残存容量)。

流网络的割(Cuts of flow networks)

流网络 G = ( V , E ) G=(V,E) G=(V,E) 中的一个割 ( S , T ) (S,T) (S,T) 将结点集合 V V V 划分为 S S S,和 T = V − S T=V-S T=VS 两个集合。使得 s ∈ S s \in S sS t ∈ T t \in T tT最小割(minimum cut) 指的是整个网络中,容量最小的切割。

Ford-Fulkerson算法:

FORD-FULKERSON ( G , s , t ) (G, s, t) (G,s,t)
1   for each edge ( u , v ) ∈ G . E (u,v) \in G.E (u,v)G.E
2      ( u , v ) . f = 0 (u,v).f=0 (u,v).f=0
3   while there exists a path p p p from s s s to t t t in the residual network G f G_f Gf
4      c f ( p ) = m i n { c f ( u , v ) : ( u , v ) c_f(p)=min\{c_f(u,v):(u,v) cf(p)=min{cf(u,v):(u,v) is in p } p\} p}
5     for each edge ( u , v ) (u,v) (u,v) in p p p
6       if ( u , v ) ∈ E (u,v) \in E (u,v)E
7          ( u , v ) . f = ( u , v ) . f + c f ( p ) (u,v).f=(u,v).f+c_f(p) (u,v).f=(u,v).f+cf(p)
8       else ( v , u ) . f = ( v , u ) . f − c f ( p ) (v,u).f=(v,u).f-c_f(p) (v,u).f=(v,u).fcf(p)

FORD-FULKERSON算法是对FORD-FULERSON-METHOD 过程的简单拓展。算法的第1~2行将流 f f f 初始化为0。算法的第 3~8行的 while 循环,重复在残存网络 G f G_f Gf 中寻找一条增广路径 p p p,然后使用残存容量 c f ( p ) c_f(p) cf(p)来对路径 p p p 上的流 f f f 进行加增。路径 p p p 上每条残存边要么是原来网络中的一条边,要么是原来网络中的边的反向边。算法第6~8行针对每种情况对流进行相应的更新:如果残存边是原来的网络中的一条边,则加增流量,否则缩减流量。当不再有增广路径时,流 f f f 就是最大流。执行第3~8行的 while 循环次数最多为 ∣ f ∗ ∣ |f^*| f次,while 循环的每一遍执行所需的时间时 O ( E ) O(E) O(E),整个算法的运行时间为 O ( E ∣ f ∗ ∣ ) O(E|f^*|) O(Ef)

Ford-Fulkerson算法例子:

接下来我用人话来举一个具体的例子来帮助大家理解。给出如下流网络 G = ( V , E ) G=(V,E) G=(V,E),接下来我们使用 Ford-Fulkerson 算法来计算这个流网络的最大流。

在这里插入图片描述

按照算法的第一步,我们将流网络的各条边流量先初始化为0。即f(s,u)=0, f(s,x)=0…等等。诶这时候问题就来了,你刚说了初始化为 0,那怎么(a)左还是和上面流网络长的是一样的啊。其实(a)左就是初始化流量为 0 的残存网络,显示的数字是该边的容量值。
接下来我们的任务就是在 残存网络 找一条 增广路径 s − > x − > y − > t s->x->y->t s>x>y>t,我上面也解释过了,增广路径其实就是从 s 到 t 的一条通路,这条通路呢你随意找,不一定是我红线标记的这一条。总而言之,无论大家这条增广路径怎么找,到最后的结果都是一样的。
找到了增广路径之后呢,我们需要选出这条路径上容量值最小的那条边,比方说(a)左就是 c ( y , t ) = 3 c(y,t)=3 c(y,t)=3,我们使这条路径的流量都为 3,即 f ( s , x ) = 3 , f ( x , y ) = 3 , f ( y , t ) = 3 f(s,x)=3, f(x,y)=3, f(y,t)=3 f(s,x)=3,f(x,y)=3,f(y,t)=3,我们得到了更新后的流网络即(a)右。

(a)在这里插入图片描述
这是个好的开始,在我们得到(a)右的基础上,我们可以生成新的残存网络(即(b)左)。在这个新的残存网络上,我们继续寻找增广路径,这时候我们发现之前边 ( y , t ) (y,t) (y,t) 已经不通了,所以我们需要换一条路。 s − > u − > v − > t s->u->v->t s>u>v>t(红线标记)。再继续找到这条路径上容量值最小的那条边( c ( u , v ) = 2 c(u,v)=2 c(u,v)=2),这条路径上的流量也设置成 2,继续更新流网络图(即(b)右)。

(b)
在这里插入图片描述
我们继续重复上一步的步骤,根据(b)右生成新的残存网络(c)左,寻找新的增广路径 s − > x − > v − > t s->x->v->t s>x>v>t,寻找容量值最小的边 c ( x , v ) = 1 c(x,v)=1 c(x,v)=1,更新流网络(c)右。

(c)在这里插入图片描述
继续,根据(c)右生成新的残存网络(d)左,寻找新的增广路径 s − > x − > y − > v − > t s->x->y->v->t s>x>y>v>t,寻找容量值最小的边 c ( x , y ) = 1 c(x,y)=1 c(x,y)=1,更新流网络(d)右。

(d)
在这里插入图片描述
终于我们根据(d)右生成新的残存网络(e)后,找不到增广路径了,这时候我们的算法到此结束了。

(e)

在这里插入图片描述
到此为止,我们可以得出这个流网络的最大流为 2+5 = 7。
接下来,我会更新 Push-Relabel 算法(推送-重贴标签算法)的内容。

  • 1
    点赞
  • 1
    评论
  • 5
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2020 CSDN 皮肤主题: 代码科技 设计师:Amelia_0503 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值