算法篇——最大流问题(概念理解)

1,903 阅读10分钟

最小费用最大流问题

最小费用最大流问题是经济学和管理学中的一类典型问题。在一个网络中每段路径都有"容量"和"费用"两个限制条件下,此类问题的研究试图寻找出:流量从A到B,如何选择路径、分配经过路径的流量,可以达到所用的费用最小的要求。

最小费用最大流建立在最大流网络流问题的基础之上。

最大流

在优化理论中,最大流问题涉及到在一个单源点单汇点网络流中找到一条最大的流。

img

每个边缘都标有容量,即可以携带的最大物品数量。 最大流问题是找出可以从顶点source到顶点sink总的物品数量(最大的那个)。

2019_10_11_2

如上图所示,当0->12->1汇聚的时候不能超出1->3的值121的输出最大为12)。最后可以到达5的最大物品个数就是19+4=23。也就是每条边和每个顶点要满足:

  • 每条边上的流量不超过每条边的给定容量。
  • sourcesink之外,每个顶点的流入流等于流出流。

相关概念:可行流与增广链

  1. 有向连通图G=(V,E);G=(V,E); V是顶点集,E是边集。

  2. 边的容量:cij;c_{ij}; (每条边的权值)

  3. 发点:vs;v_{s}; 收点:vt;v_{t}; 其他的点叫中间点。(或者说源点和汇点)

  4. (vi,vj)(v_i,v_j)有流量fijf_{ij},集合f=fijf={f_{ij}} 为G的一个流。(边上已经实际有流量了)

  5. 重点ff为可行流满足:第一点:容量限制条件:对于任意一条边来说,实际的流量一点更要小于容量,即0<=fij<=fij0<=f_{ij}<=f_{ij};

    ​ 第二点:流量平衡条件:对于所有的中间节点viv_i来说,流入它的流量和从它流出的流量是相等的。即fki=fij\sum{f_{ki}}=\sum{f_{ij}}

  6. 对于收点viv_i和发点vsv_s,有ifsi=jfjt=W\mathop{\sum} \limits_{i}f_{si}=\mathop{\sum} \limits_{j}f_{jt}=W ,W为总流量(源头流出的等于终点流入的,在中间节点流量没有损失)

  7. μ\mu 为G上从vsv_svtv_t的链,规定vsv_svtv_t为链μ\mu的方向,链上与μ\mu方向一致的边叫前向边,与μ\mu 方向相反的边成为后向边。

    例:image-20201025130547588

    μ:v1>v2>v3>v4>v6\mu:v_1->v_2->v_3->v_4->v_6

    前向边:(v1,v2),(v3,v4),(v4,v6)(v_1,v_2),(v_3,v_4),(v_4,v_6)

    后向边:(v2,v3)(v_2,v_3)

  8. 若链μ\mu中的前向边(vi,vj)(v_i,v_j)必有fij<cijf_{ij}<c_{ij},后向边上必有fij>0f_{ij}>0,称μ\mu是关于可行流fij{f_{ij}}的一条增广链。(前向边:流量<容量,后向边非零流)

构造一个可行流

image-20201025131335684

括号前面的哪个是容量,后面哪个是实际流量。

v3v_3为例,流进3,流出总量也是3;发点流出4,收点流进4,所以当前网络图总流量W=4。当前的流ff是可行流。

再检查一下:μ:v1>v2>v3>v4>v6\mu:v_1->v_2->v_3->v_4->v_6

前向边:(v1,v2),(v3,v4),(v4,v6)(v_1,v_2),(v_3,v_4),(v_4,v_6) 流量小于容量

后向边:(v2,v3)(v_2,v_3) 后向边流量>0

此时链μ\mu 是一条可增广链,也叫增广链,代表在这条链上,我们是可以增加流量的。

对增广链可做如下调整:

δij={cijfij(vi,vj)为前向边;fij(vi,vj)为后向边\delta_{ij}=\begin{cases} c_{ij}-f_{ij},(v_i,v_j)为前向边;\\ f_{ij}, (v_i,v_j)为后向边\end{cases}

δ=min{δij}\delta=min\{\delta_{ij}\}

把流改成f1:f1={fij+δ,(vi,vj)μ上前向边fijδ,(vi,vj)μ上后向边f_1:f_1=\begin{cases}f_{ij}+\delta,(v_i,v_j)为\mu上前向边\\f_{ij}-\delta,(v_i,v_j)为\mu上后向边 \end{cases}

前向边增加流量,后向边减少流量

由题意,μ\mu上只能调整一个流量,此时对增广链μ\mu做调整,调整后的可行流如图所示:

image-20201025134409652

那么新的可行流是不是最大流呢?

最小割集

我们使用最小割集检验:

  1. 容量网络G=(V,E,C)G=(V,E,C),顶点集V满足ST=V,ST=S\bigcup T=V,S \bigcap T=\empty,且vsS,vtTv_s\in S,v_t \in T, 令:(S,T)={(vi,vj)EviS,vjT}(S,T)=\{(v_i,v_j)\in E |v_i \in S,v_j\in T\}

(S,T)(S,T)为分离vsvtv_s和v_t的一个割集。

把V分成两半,一个是S一个是T,发点在集合S里,收点在集合T中。

例:V={v1,v2,v3,v4,v5,v6}V=\{v_1,v_2,v_3,v_4,v_5,v_6\};

S={v1,v2,v3}S=\{v_1,v_2,v_3\}T={v4,v5,v6}T=\{v_4,v_5,v_6\}

(S,T)={(v2,v4),(v3,v4),(v3,v5)}(S,T)=\{(v_2,v_4),(v_3,v_4),(v_3,v_5)\}

所有边的起点都在集合S中,所有边得终点都在集合T中,这个(S,T)就是一个割集。

要想从起点走到终点的话,割集里的三条边是必经之路。

割集并不唯一。

  1. 割集(S,T)中所有边的容量之和成为该割集的最小容量;

​ 在G的所有割集中,割集容量最小者称为G的最小割。(也就是网络图中能通过的最小的瓶颈部分,也就是漏桶中的那块最短板,要想让整个网络图的流量增加的话,一定要解决瓶颈部位的流量问题)

最大流,最小割定理

定义:在任意一个网络G中,从发点vs到收点vtv_s到收点v_t的最大流流量等于最小割的容量。

求最大流的标号算法:

设已有一个可行流ff,标号法分为两步:

  1. 标号过程(通过标号寻找增广链)
  2. 调整过程(沿增广链调整ff增加流量)

整个过程:

1.找可行流 2.找增广链(如果能找到增广链,执行第三步。如果找不到增广链,当前已经是最优解)3.调整

image-20201025142627824 image-20201025142650584

解最大流问题的Ford-Fulkerson解法

www.cnblogs.com/DarrenChan/…

本文主要讲解最大流问题的Ford-Fulkerson解法。可以说这是一种方法,而不是算法,因为它包含具有不同运行时间的几种实现。该方法依赖于三种重要思想:残留网络,增广路径和割。

在介绍着三种概念之前,我们先简单介绍下Ford-Fulkerson方法的基本思想。首先需要了解的是Ford-Fulkerson是一种迭代的方法。

开始时,对所有的u,v属于V,f(u,v)=0(这里f(u,v)代表u到v的边当前流量),即初始状态时流的值为0。

在每次迭代中,可以通过寻找一个“增广路径”来增加流值。增广路径可以看做是从源点s到汇点t之间的一条路径,沿该路径可以压入更多的流,从而增加流的值。反复进行这一过程,直到增广路径都被找出为止。

残留网络

顾名思义,残留网络是指给定网络和一个流,其对应还可以容纳的流组成的网络。具体说来,就是假定一个网络G=(V,E),其源点s,汇点t。设f为G中的一个流,对应顶点u到顶点v的流。在不超过C(u,v)的条件下(C代表边容量),从u到v之间可以压入的额外网络流量,就是边(u,v)的残余容量(residual capacity),定义如下:

r(u,v)=c(u,v)-f(u,v)

举个例子,假设(u,v)当前流量为3/4,那么就是说c(u,v)=4,f(u,v)=3,那么r(u,v)=1。

我们知道,在网络流中还有这么一条规律。从u到v已经有了3个单位流量,那么从反方向上看,也就是从v到u就有了3个单位的残留网络,这时r(v,u)=3。可以这样理解,从u到v有3个单位流量,那么从v到u就有了将这3个单位流量的压回去的能力。

f1:f1={fij+δ,(vi,vj)μ上前向边fijδ,(vi,vj)μ上后向边f_1:f_1=\begin{cases}f_{ij}+\delta,(v_i,v_j)为\mu上前向边\\f_{ij}-\delta,(v_i,v_j)为\mu上后向边 \end{cases}

所以后向边可以把流量压回去给前向边

我们来具体看一个例子,如下图所示一个流网络

img

其对应的残留网络为:

img

增广路径

在了解了残留网络后,我们来介绍增广路径。已知一个流网络G和流f,增广路径p是其残留网络Gf中从s到t的一条简单路径。形象的理解为从s到t存在一条不违反边容量的路径,向这条路径压入流量,可以增加整个网络的流值。上面的残留网络中,存在这样一条增广路径:

img

其可以压入4个单位的流量,压入后,我们得到一个新的流网络,其流量比原来的流网络要多4。这时我们继续在新的流网络上用同样的方法寻找增广路径,直到找不到为止。这时我们就得到了一个最大的网络流。

流网络的割

上面仅仅是介绍了方法,可是怎么证明当无法再寻找到增广路径时,就证明当前网络是最大流网络呢?这就需要用到最大流最小割定理。

首先介绍下,割的概念。流网络G(V,E)的割(S,T)将V划分为S和T=V-S两部分,使得s属于S,t属于T。割(S,T)的容量是指从集合S到集合T的所有边(有方向)的容量之和(不算反方向的,必须是S-àT)。如果f是一个流,则穿过割(S,T)的净流量被定义为f(S,T)(包括反向的,SàT的为正值,T—>S的负值)。将上面举的例子继续拿来,随便画一个割,如下图所示:

img

割的容量就是c(u,w)+c(v,x)=26

当前流网络的穿过割的净流量为f(u,w)+f(v,x)-f(w,v)=12+11-4=19

显然,我们有对任意一个割,穿过该割的净流量上界就是该割的容量,即不可能超过割的容量。所以网络的最大流必然无法超过网络的最小割。

首先,我们必须了解一个特性,根据上一篇文章中讲到的最大流问题的线性规划表示时,提到,流网络的流量守恒的原则,根据这个原则我们可以知道,对网络的任意割,其净流量的都是相等的。具体证明是不难的,可以通过下图形象的理解下,

img

现在来证明当残留网络Gf中不包含增广路径时,f是G的最大流。

假设Gf中不包含增广路径,即Gf不包含从s到v的路径,定义S={v:Gf中从s到v存在一条通路},也就是G**f中s能够有通路到达的点的集合,显然这个集合不包括t,因为s到t没有通路。这时,我们令T=V-S。那么(S,T)就是一个割。**如下图所示:

img

么,对于顶点u属于S,v属于T,有f(u,v)=c(u,v)。否则(u,v)就存在残余流量,因而s到u加上u到v就构成了一条s到v的通路,所以v就必须属于S,矛盾。因此这时就表明当前流f是等于当前的割的容量的,因此f就是最大流。

Ford-Fulkerson方法

Ford-Fulkerson方法的正确性依赖于这个定理:当残存网络中不存在一条从s到t的增广路径,那么该图已经达到最大流。这个定理的证明及一些与其等同的定理可以参考《算法导论》。

Ford-Fulkerson方法的伪代码如下。其中<u,v>代表顶点u到顶点v的一条边,<u,v>.f表示该边的流量,c是边容量矩阵,c(i,j)表示边<i,j>的容量,当边<i,j>不存在时,c(i,j)=0。e为残存网络矩阵,e(i,j)表示边<i,j>的值,当边<i,j>不存在时,e(i,j)=0。E表示边的集合。f表示流网络。

Ford-Fulkerson伪代码

for <u,v> ∈ E
 
    <u,v>.f = 0//初始化流量为0
 
while find a route from s to t in e
 
    m = min(<u,v>.f, <u,v>  ∈ route)
 
    for <u,v> ∈ route
 
        if <u,v>  ∈ f
 
            <u,v>.f = <u,v>.f + m
 
        else
 
            <v,u>.f = <v,u>.f - m

Ford-Fulkerson方法首先对图中的所有边的流量初始化为零值,然后开始进入循环:如果在残存网络中可以找到一条从s到t的增广路径,那么要找到这条这条路径上值最小的边,然后根据该值来更新流网络

Ford-Fulkerson有很多种实现,主要不同点在于如何寻找增广路径。最开始提出该方法的Ford和Fulkerson同学在其论文中都是使用广度优先搜索实现的,其时间复杂度为O(VE),整个算法的时间复杂度为O(VE^2)。

  1. find an augmenting path

  2. compute the bottleneck capacity

  3. augment each edge and total flow

  4. 我们需要输入点数和边数构造网络。

  5. 边包括起点、终点、流量和最大容量

  6. 我们需要构造残留网络,增广路径

  7. 残留网络的边包括起点终点和流量