前言
最短路径解决的是一个成本问题。而生活中一些问题需要考虑更多的因素,如通讯中的“带宽”;物流中的“路宽”…。我们把这类问题,归结为“网络流” 问题。 即如 容量限制。即把这物流方面的问题,称为“流网络”。网络流,它分为两部分:网络和流。
- 网络,其实就是一张有向图,其上的边权称为容量。额外地,它拥有一个源点和汇点。
- 流,顾名思义,就像水流或电流,也具有它们的性质。如果把网络想象成一个自来水管道网络,那流就是其中流动的水。每条边上的流不能超过它的容量,并且对于除了源点和汇点外的所有点(即中继点),流入的流量都等于流出的流量。
网络流
一个带权有向图 G = ( V , E ) G=(V,E) G=(V,E),其中 V是图中所有点的集合, E是所有边的集合,且每一条边都有其流量上限。
这个带权有向图中有两个特殊的点:源(source)节点 s 和汇(sink)节点 t,且这两个点满足 s , t ∈ V , s ≠ t s,t\in V, s\ne t s,t∈V,s=t。从 s 到 t 的流函数 f将这个有向图中的每条边 e 映射到一个非负实数,即 f(e) 表示边 e所承载的流量。
作为流网络,这个带权有向图需要满足两个条件:
- 容量条件,流网络中任意边上的流量不超过流网络的容量,即对于任意边 e ∈ E e\in E e∈E ,有 0 ⪯ f ( e ) ≤ c e 0\preceq f(e)\leq c_{e} 0⪯f(e)≤ce
- 守恒条件,对于非源节点和汇节点的任意内部节点 e ,流入该结点的流量之和等于流出该结点的流量之和,即 ∑ i n f ( e ) = ∑ o u t f ( e ) \sum_{in}^{ }{f(e)}=\sum_{out}^{ }{f(e)} ∑inf(e)=∑outf(e)
最大流问题就是求解源节点和汇节点之间的最大流量
反平行边的问题
多个源点和多个汇点的网络
Ford-Fulkersion方法
之所以称其为“方法”,而不是“算法”。是因为它包含了几种运行时间各不相同的具体实现。Ford-Fulkersion方法主要依赖于三种重要的思想:残存网络,增广路径和切割。
残存网络
对于给定流 f,
G
f
G_f
Gf是流网络
G
=
(
V
,
E
)
G =(V,E)
G=(V,E)中所有结点和残存容量
c
f
c_f
cf大于0的边所构成的子图,即:
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)
G
f
=
(
V
f
=
V
,
E
f
=
{
(
u
,
v
)
∈
E
:
c
f
(
u
,
v
)
>
0
}
G_f = (V_f = V, E_f = \{(u,v) \in E : c_f(u,v) \gt 0 \}
Gf=(Vf=V,Ef={(u,v)∈E:cf(u,v)>0}
残存容量 c f c_f cf, 表示的是这条边容量与流量的**差值.**即此边还可以通行的流量
需要注意的是,残存网络 G f G_f Gf还可能包含图 G中不存在的边。算法对流量进行操作的目标是增加总流量,为此,算法可能对某些特定边上流量进行缩减。为了表示对一个正流量 f ( u , v ) f(u,v) f(u,v)的缩减,我们将边 ( u , v ) (u,v) (u,v)加入到图 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)。也就是说,一条边所能允许的反向流量最多将其正向流量抵消。
也就是,对于一个流网络 G = ( V , E ) G=(V,E) G=(V,E),设f为图 G中的一个流,考虑对于结点对 u , v ∈ E u,v \in E u,v∈E,残存容量 c f ( u , v ) c_f(u,v) cf(u,v)的值为下列三种情况之一:
c f ( u , v ) = { c ( u , v ) − f ( u , v ) if ( u , v ) ∈ E f ( v , u ) if ( v , u ) ∈ E 0 other c_f(u,v) = \begin{cases} c(u,v)-f(u,v) &\text{if } (u,v) \in E \\ f(v,u) &\text{if } (v,u) \in E \\ 0 &\text{other } \end{cases} cf(u,v)=⎩⎪⎨⎪⎧c(u,v)−f(u,v)f(v,u)0if (u,v)∈Eif (v,u)∈Eother
举个例子,下图中,a 为流网络G,b 为流网络上G的一个流 f,c 为f引导出的残存网络
G
f
G_f
Gf。
以图中
(
s
,
v
1
)
(s, v_1)
(s,v1)这条边为例,
- 流网络G中该边的容量为16,
- 在流f中该边的流为 11,则还可以对 f ( s , v 1 ) f(s, v_1) f(s,v1) 增加的量最大为 5,再多就将超过边 ( s , v 1 ) (s, v_1) (s,v1)的容量限制。
- 同时,从结点 v 1 v_1 v1向结点s最多可以返回 11个单位的流量,也就是从s到 v 1 v_1 v1最多可以缩减11 个单位,因此, c f ( v , u ) = 11 c_f(v,u) = 11 cf(v,u)=11
增广路径
给定流网络
G
=
(
V
,
E
)
G=(V,E)
G=(V,E)和流 f ,增广路径 p 是残存网络
G
f
G_f
Gf中从源结点s到汇点 t到简单路径。根据残存网络到定义,对于一条增广路径上的边
(
u
,
v
)
(u,v)
(u,v),我们可以增加其流量的幅度最大为
c
f
(
u
,
v
)
c_f(u,v)
cf(u,v),而不会违反原始流网络G中对边
(
u
,
v
)
(u,v)
(u,v)或
(
v
,
u
)
(v,u)
(v,u)的容量限制。
增广路径p 上能够为每条边增加的流量的最大值为增广路径p 的残存容量,即:
c
f
(
p
)
=
m
i
n
{
c
f
(
u
,
v
)
:
(
u
,
v
)
∈
P
}
c_f(p) = min\{c_f(u,v):(u,v) \in P \}
cf(p)=min{cf(u,v):(u,v)∈P}
流网络的切割
流网络 G = ( V , E ) G=(V,E) G=(V,E)中的一个切割 ( S , T ) (S,T) (S,T) 将结点集合V 划分为 S 和 T= V-S两个集合,使得 s ∈ S , t ∈ T s \in S,t \in T s∈S,t∈T。
-
净流量:若f是一个流,则定义横跨切割 ( S , T ) (S,T) (S,T) 的净流量 f ( S , T ) f(S,T) f(S,T)为: f ( S , T ) = ∑ u ∈ S ∑ v ∈ T f ( u , v ) − ∑ u ∈ S ∑ v ∈ T f ( v , u ) f(S,T) = \sum_{u \in S} \sum_{v \in T} f(u,v) - \sum_{u \in S} \sum_{v \in T} f(v,u) f(S,T)=u∈S∑v∈T∑f(u,v)−u∈S∑v∈T∑f(v,u)
-
割的容量:切割 ( S , T ) (S,T) (S,T)的容量为所有从S到 T 的边的容量之和,即:
c ( S , T ) = ∑ u ∈ S ∑ v ∈ T c ( u , v ) c(S,T) = \sum_{u \in S} \sum_{v \in T} c(u,v) c(S,T)=u∈S∑v∈T∑c(u,v) -
最小切割:整个网络中容量 c ( S , T ) c(S,T) c(S,T)最小的切割。
上图表示流网络的一个切割
(
{
s
,
v
1
,
v
4
}
,
{
v
2
,
v
3
,
t
}
)
(\{s, v_1, v_4 \},\{ v_2, v_3, t \})
({s,v1,v4},{v2,v3,t}):
- 净流量: f ( v 1 , v 2 ) + f ( v 4 , v 3 ) − f ( v 2 , v 4 ) = 12 + 11 − 4 = 9 f(v_1, v_2) + f(v_4, v_3)-f(v_2, v_4) = 12 +11 -4 = 9 f(v1,v2)+f(v4,v3)−f(v2,v4)=12+11−4=9
- 割的容量: c ( v 1 , v 2 ) + c ( v 4 , v 3 ) = 12 + 14 = 26 c(v_1, v_2) + c(v_4, v_3)= 12 +14 = 26 c(v1,v2)+c(v4,v3)=12+14=26
最大流最小割定理
设 f是流网络 G = ( V , E ) G=(V,E) G=(V,E)中的一个流,该流网络的源结点为 s ,汇点为 t,则下面的条件是等价的:
- f 是 G 的一个最大流。
- 残存网络 G f G_f Gf不包括任何增广路径。
- 净流量 ∣ f ∣ = c ( S , T ) |f|=c(S,T) ∣f∣=c(S,T),其中 ( S , T ) (S,T) (S,T)是流网络G的某个切割。
基本的Ford-Fulkerson的实现
在Ford-Fulkerson方法的每次迭代中,寻找某条增广路径p,然后使用p 来对流 f来进行修改,从而获得一个值为 ∣ f ∣ + ∣ f p ∣ |f| + |f_p| ∣f∣+∣fp∣ 的更大的流。
我们为每条边 ( u , v ) ∈ E (u,v) \in E (u,v)∈E, 容量为 c ( u , v ) c(u,v) c(u,v), 更新流属性 ( u , v ) . f (u,v).f (u,v).f 来计算流网络 G = ( V , E ) G=(V,E) G=(V,E)中的最大流。
- 如果边 ( u , v ) ∉ E (u,v) \notin E (u,v)∈/E,则设 ( u , v ) . f = 0 (u,v).f = 0 (u,v).f=0。
- 如果边 ( u , v ) ∉ E (u,v) \notin E (u,v)∈/E,则 c ( u , v ) = 0 c(u,v)=0 c(u,v)=0。
根据上述公式计算残存容量 c f ( u , v ) c_f(u,v) cf(u,v)。
FORD-FULKERSON(G, s, t)
for each edge(u,v) in G.E
(u, v).f = 0
while there exit a path p from s to t in the residual network Gf
cf(p) = min{cf(u,v) : (u,v) is in p}
for each edge(u,v) in p
if(u,v) in G.E
(u,v).f = (u,v).f + cf(p)
else (u,v).f = (v,u).f - cf(p)
算法重复在残存网络 G f G_f Gf中寻找一条增广路径 p ,然后使用残存容量 c f ( p ) c_f(p) cf(p)来对路径 p上的流 f进行增加。路径p上的每条残存边要么是原来网络中的一条边,要么是原来网络中的一条反向边。算法根据这两种情况进行相应的更新:如果是原来网络中的一条边,则增加流,否则缩减流。当不在有增广路径时,流f 就是最大流。
最大二分匹配
在一群人中,有一些人可以俩俩友好的共住一个房间,在什么条件下,可以将所有这群人俩俩配对,安排它们共住一套房屋呢?类似问题在生活中很常见,比如如说男女配对问题。
图表示
图
G
=
(
V
,
E
)
G=(V,E)
G=(V,E) 的一个 匹配 是由一组没有公共端点的不是圈的边构成的集合。换句话说,也就是,一组俩俩没有公共结点的边集称为图 G 的匹配。可以看出匹配是图边E的一个子集
M
⊆
E
M \subseteq E
M⊆E。其中匹配中的边称为 匹配边,反之称为 未匹配边。
二分图中,结点集合可以划分为
V
=
L
∪
R
V = L \cup R
V=L∪R,其中 L 和 R是不相交的,并且边的集合 E中所有边都横跨 L 和 R。
一个匹配是由若干条边构成,故其大小就是边的数量( ∣ M ∣ |M| ∣M∣)。最大匹配顾名思义就是大小最大的匹配。
寻找最大二分匹配
将二分图
G
=
(
V
,
E
)
G=(V,E)
G=(V,E) 转为对应的流网络
G
′
=
(
V
′
,
E
′
)
G'=(V',E')
G′=(V′,E′),给
E
′
E'
E′ 中的每条边赋予单位容量。
二分图 G 的一个最大匹配对应于流网络
G
′
G'
G′中的一个最大流,因此可以通过在对应流网络
G
′
G'
G′上运行一个最大流算法(EK)来计算图G的最大匹配。
主要参考
《流网络,流和增广路算法基础》
《详解最大流问题和Ford-Fulkerson算法》
《最大二分匹配》
《Maximum Flow》