跟我一起学算法——最大流

@

定义

最大流(Maximum Flow)

流网络((flownetwork))

在有向图 G 中,流是一实函数 f:V×VR,并满足以下三个条件:
容量限制 :对于所有的 u,v∈V,f(u,v)≤c(u,v)
反对称性 :对于所有的 u,v∈V,f(u,v)= -f(v,u)
流守恒 (流进=流出):图中每条边(u,v)∈E 均为非负 容量 c(u,v)≥0。如果(u,v)不
属于E,则 c(u,v)=0。
源s,汇t
某个顶点的 总净流 定义为:净流=流出总正流-流入总正流

多源多汇

加入s和t就可变成单源单汇

剩余网络(residual network)

剩余网络就是在流网络中除去某个流后, 所有剩余容量(residual capacity)组成的网络。
剩余流量:二个顶点u,v间的剩余容量定义为:c_f(u,v)=c(u,v)-f(u,v)
对于给定的流网络G=(V,E)以及流f,则G_f(V,E_f) 是相对与流f的剩余网络。

增广路径((Augmenting Path)

从s到t的简单路径p。
c_f(p) = min(c_f(u,v) ; (u,v) ∈ p) , 即增广路径的最大流量由p中边的最小容量决定。
令f是流网络G=(V,E)的一个流,令P是剩余网络Gf的一 条增广路径。定义函数f_p:V×V->R,则
f_p是G_f的一个流且流值为 |f_p|=c_f(P)>0
定义函数f’:V×V->R且f’=f+fp,那么f’ 是G中的一个流,其流值|f’|=|f|+|f_p|>|f|。

截(Cut)

流网络的截(S,T)是顶点V的一种划分,其中T=V-S, s∈S,t∈T。
流函数f(S,T):穿越截(S,T)的净流,即流出总正流- 流入总正流。
C(S,T):截(S,T)的容量,即从S到T的容量之和。
最小截:所有截中容量最小的截。
任意截(S,T)的净流f(S,T)=|f|。
流网络G中的任何流值均受限于G中截的容量限制, f(S,T)<=c(S,T)

最大流最小截定理:如果f是源为s汇为t的流网络G中的一个流,那么以下条件相等:f是G中的最大流<=>
剩余网络没有增广路径 <=> G中存在截(S,T),使|f|=C(S,T)
参考https://www.jianshu.com/p/beca253fdc9f

Ford-Fulkerson算法

Ford-Fulkerson-Method(G,s,t)
  初始化流f=0
  while 存在增广路径P
    do 沿增广路径P增加流f
    根据增加的流,更新边的容量
  return f

时间复杂度O(fE) , f为增广路径的数量,可大可小。

Edmonds-Karp算法

Edmonds-Karp 算法是 Ford-Fulkerson 方法的一种具体实现。它采用 BFS 搜索方法在剩余网络
中寻找增广路径。具体做法是先对每条边的权值统一赋值为 1,然后找一条从 s 到 t 的最短
路径。基于此方法,Edmonds-Karp 算法求最大流的时间为 O(VE^2)。

应用:最大二分图匹配(Maximum Bipartite Matching)

  1. 二分图
    把顶点集V划分为二个不相交的子集合L和R,即 V=L∪R,L∩R=Φ,并且只有L和R之间存在边,L、R
    内部的顶点间没有边,则称这样的图为二分图。

  2. 匹配
    二分图中具有最多边的匹配称为最大二分图匹配

  3. 求二分图的最大匹配问题
    首先需把二分图转换为流网络:

  • 增加一个源s和汇t及s到L中所有顶点的边以及R中所有顶点到t的边
  • 把无向图改为有向图,方向为s->L->R->t
  • 给所有边赋值为单位容量值
  1. 二分图G的一个最大匹配M的目数等于其相关流 网络G’的最大流f的流值。

  2. 算法时间为O(VE)

Push-relable算法

定义

  1. 预流
    V中除了s,t外的v不满足流守恒,若v的净流>=0,称为溢出顶点。

  2. 高度
    h(s)=|V| , h(t)=0 ,保持不变
    其他顶点高度初始化为0,h(u) = 0
    对于边(u,v),h(u)<=h(v)+1

push

三个条件:

  1. u为溢出顶点
  2. h(u)=h(v)+1
  3. 存在边容量>0,c_f(u,v)>0

Push操作:
向下推的流量d=min(e(u), c_f(u,v)),即取u的净流与边容量的较小值,取后者时称为饱和push。
e(v) += d
e(u) -= d
push后 u,v 之间建立一条反向的容量为d的边,也可以直接抵消正向容量。

relable

两个条件:

  1. u为溢出顶点
  2. h(u)<=h(v)

操作:
h(u) = 1 + min(h(v)) , v与u相连的顶点。

初始化(init)

  1. 高度初始化
  2. 把s的流以容量为限推到与之相连的各个顶点,e(u)=c(s,u)

算法

push_relanble(G)
  init_preflow(G)
  while there exists a vertex that can be pushed or relabled
    do choose push or relable at will

参考

《算法导论》
https://www.jianshu.com/p/beca253fdc9f

posted @ 2020-03-03 15:16  chzhyang  阅读(985)  评论(0编辑  收藏  举报