流网络
网络流G=(v, E)是一个有向图,其中每条边(u, v)均有一个非负的容量值,记为c(u, v) ≧ 0。如果(u, v) ∉ E则可以规定c(u, v) = 0。网络流中有两个特殊的顶点,即源点s和汇点t。
与网络流相关的一个概念是流。设G是一个流网络,其容量为c。设s为网络的源点(source),t为汇点(sink),那么G的流是一个函数f:V×V →R,满足以下性质:
如图:
就是在容量容许的条件下,从源点到汇点所能通过的最大流量
在这之前,先看几个定义。
定义:增广路径是找出在残留网络中从源点到汇点的有向路径。增广路径的残留容量是路径中任意边所形成的最小残留容量。显然,我们可以沿着增广路径从源点到汇点发送额外的流。
通过寻找增广路径,我们可以迭代的增加流的值
如何寻找增广路径?
在残量图中找
定义:
残量边:
残量图:
bottleneck是一条路径中最小的那个容量
构造残量图不用真的构造,有trick(俺也不知道,等俺想到了补上)
Augment(f,c,P)
b=bottleneck(P)
for each e ∈ P
if (e∈E) f(e)=f(e)+b
else f(eR)=f(e)-b
return f
Ford-Fulkerson(G,c,s,t)
{
for each e∈E f(e)=0
Gf= residual graph
while(there exists augmenting path P in Gf)
f=Augment(f,c,P)
update Gf
return f
}
v(f')=v(f)+bottleneck(P,f)
并且只要bottleneck(P,f)>0,则有v(f')>v(f)
实数可以作为容量吗?
在实际应用中,容量一般是整数和有理数。如果容量带小数,可能会遇到循环多次,每次流只增加一点点,循环很难结束的情况
引入割的概念
定义:是网络中顶点的一个划分,把所有顶点划分成两个顶点集合A和B,其中源点s属于A,汇点t属于B,记作(A,B)
即为求一个最小容量的割
设f是任意s到t的流,(A,B)是任意s到t的割,则经过割的净流量等于s输出的流量
如图,三个割的净流量都是等于s输出的流量24
证明:
设f是任意s到t的流,(A,B)是任意s到t的割,则流的最大值最多能到割的容量,即v(f)<=cap(A,B)
证明:
推论:设f是任意s到t的流,(A,B)是任意s到t的割,如果v(f)=cap(A,B),则f是最大流,(A,B)是最小割
最大流的值等于最小割的值
f是s到t的最大流当且仅当没有增广路径时
证明策略:这三个性质可以相互推导
(1)存在一个割(A,B)满足v(f)=cap(A,B)
(2)流f是最大流
(3)没有与f有关的增广路径
(1)推导(2):弱对偶性的推论(不懂……)
(2)推导(3):反证法:如果f存在增广路径,则f还可以增长,则f不是最大流
(3)推导(1):
构造性证明,对条件(3),求出割(A,B)满足v(f)=cap(A,B)
设流f没有增广路径
设A是残量图中从源点s出发的一系列可达的顶点的集合
进入A的边f(e)=0,从A出来的边的f(e)等于c(e)
反推:
如果一条边进入A且f(e)不为0,那么这条边的起点应该在A里
如果一条边从A出来且f(e)不等于c(e),那么这条边的终点也在A里(俺也没明白,到底啥意思啊……)
那么如何来求出最小割的其中一种方案呢,我们在进行最大流计算完成之后,从原点进行遍历整张图,将遍历到的点标记为 true
;最终结束之后,所有标记为 true
的点和没有标记的点之间就是一个割边。
那么为什么求出来的就是割边呢,因为最大流之后,所有通路在满流的那条通道处断掉了,也就是没有办法继续走下去,而这条通道一边标记为了 true
另一边没有被标记,那么他们之间就是一个割边了。
证明很简单,因为每次求路径p的瓶颈肯定是整数,求残量图的容量也是整数,再求增广路径上的容量也还是整数,所以最大流一定是整数