流网络
流网络G(V,E)是一个有向图,每条边有一个非负的容量值c,且每条边没有重边(反向边)。如果两个节点没有边,为了方便我们设置其流量值为0
在流网络的所有节点中,我们特别地有两个节点:源节点s和汇点t。我们假定每个节点都在s和t之间,从而形成一个流
对于流网络,我们有两个性质:
1.容量守恒:对于所有节点间,两点流量小于等于其间容量
2.流量守恒:流进一个节点的流量等于流出这个节点的流量。
边上的数值:分子表示流,分母表示容量
问题描述
在最大流问题中,给定一个流网络G、一个源节点s、一个汇点t,希望找到一个值最大的一个流
Ford-Fulkerson方法
这个方法依赖于三种重要思想:残存网络,增广路径,切割
残存网络
对节点u、v,定义残存容量为
残存网络可能包含图G中不存在的边,残存网络中的反向边允许算法将已经发送出来的流量发送回去。一个残存网络示例图如下:
图a是一个流网络,b是a对应的残存网络。
注意每条边上的值,残存网络中针对每条正向边计算出该条边在存在流的情况下的剩余容量,并画出一条反向边,反向边的容量即是发出流的大小,方便将发出的流运输回发送地,并将权重为0的边省略。
残存网络是如何增大原始流网络中的流的一种指示
如果f是G的一个流,对应的有一个残存网络,残存网络中我们可以定义一个流 f ’
又定义一个函数,为流f’对流f的增量(或递增),它是一个VxV到R的函数
增广路径
给定流网络G和流f,增广路径p是残存网络中一条从源结点s到汇点t的简单路径
我们称在一条增广路径p上能够为每条边增加的流量的最大值为路径p的残存容量。表示为cf(p)
引理 设G为一个流网络,设f为图G中的一个流,设p为残存网络中的一条增广路径。定义一个函数如下:
fp为残存网络的一个流,其值大于0
有了增广路径,使得我们找到的流更接近于最大流
切割
Ford算法核心就是沿着增广路径重复增加路径上的流量,直到找到一个最大流为止。但我们怎么知道找到了呢?
定理:一个流是最大流当且仅当其残存网络不包含任何增广路径
切割:一个切割(S,T)将图G(V,E)的节点集合V划分为S和T=V-S两个集合,使得节点s属于S,t属于T。
若f为一个流,则定义横向切割(S,T)的净流量f(S,T)如下:
切割(S,T)的容量是:
一个网络的最小切割是整个网络中容量最小的切割。
如对于这个流网络:
该切割净流量:
该切割的容量:(只看从s到t方向的容量)
引理 设f为流网络G的一个流,该流网络的源结点为s,汇点为t,设(S,T)为流网络G的任意切割,则横跨切割(S,T)的净流量为f(S,T)= |f|。
推论 流网络G中任意流f的值不能超过G的任意切割的容量。
最大流最小切割定理
设f为流网络G=(V,E)中的一个流,该流网络的源结点为s,汇点为t,则下面的条件是等价的:
- f是G的一个最大流。
- 残存网络不包含任何增广路径
- |f|=c(S,T),其中(S,T)是流网络G的某个切割。
因为一个流不可能大于一个切割容量,当一个切割容量最小时,其值就为最大流的大小
基本的Ford算法
在Ford-Fulkerrson方法的每次迭代中,寻找某条增广路径p,然后使用p来对流f进行修改(增加)。找到一条增广路径后有对应的fp,将其添加到f中,知直到找不到一条增广路径p为止。
伪代码
1-2行:初始化流
3-8行:在残存网络中寻找一条增广路径p,然后使用残存容量cf(p)来对流f加增。
因为路径p上每条残存边要么是原来网络中一条边,要么是原来网络中一条反向边。
故6-8行:如果残存边为原来一条边,加增流量;为反向边,减流量。
当没有增广路径p时,流f就是最大流
算法运行时间取决于寻找增广路径的时间,当我们使用基于广度优先搜索的算法时,此时称Ford算法为Edmonds-Karp算法,算法时间复杂度为O(V*E^2)