一、问题定义
1.1 流网络
给定有向图 G = < V , E , C > G=<V,E,C> G=<V,E,C>,其被称为流网络:
- 容量: ∀ e ∈ E , c ( e ) ≥ 0 \forall e \in E, c(e) \ge0 ∀e∈E,c(e)≥0
- 流量: ∀ e ∈ E , 0 ≤ f ( e ) ≤ c ( e ) \forall e \in E, 0 \leq f(e) \leq c(e) ∀e∈E,0≤f(e)≤c(e)
- 剩余容量: ∀ e ∈ E , c ( e ) − f ( e ) \forall e \in E, c(e)-f(e) ∀e∈E,c(e)−f(e)
- 总流量: ∣ f ∣ = ∑ e out of s f ( e ) = ∑ e in to t f ( e ) |f|={\textstyle \sum_{\text{e out of s}}f(e) =\textstyle \sum_{\text{e in to t}}f(e) } ∣f∣=∑e out of sf(e)=∑e in to tf(e) (总流量 = 源点流出量 = 汇点流入量)
1.2 最大流问题
输入:
①有向图 G = < V , E , C > G=<V,E,C> G=<V,E,C>,其中, c ( e ) ∈ C c(e)\in C c(e)∈C表示边 e e e的容量
②源点 s s s,汇点 t t t
输出: 总流量 ∣ f ∣ |f| ∣f∣
约束目标: m a x ∣ f ∣ = m a x ∑ e out of s f ( e ) max|f|=max {\textstyle \sum_{\text{e out of s}}f(e)} max∣f∣=max∑e out of sf(e)
约束条件:
\quad ①容量限制: 0 ≤ f ( e ) ≤ c ( e ) 0\leq f(e)\leq c(e) 0≤f(e)≤c(e) (边上的流量不能超过容量)
\quad ②流量守恒: ∑ e in to v f ( e ) = ∑ e out of v f ( e ) {\textstyle \sum_{\text{e in to v}}f(e)} = {\textstyle \sum_{\text{e out of v}}f(e)} ∑e in to vf(e)=∑e out of vf(e) (每个顶点进入和流出的流量和相等)
二、算法策略
2.1 算法引入
直观想法:
①对 ∀ e ∈ E \forall e \in E ∀e∈E,初始化流量为 f ( e ) = 0 f(e)=0 f(e)=0
②寻找一条源点 s s s到汇点 t t t的路径 P P P,此路径上的每条边 e e e均满足 f ( e ) < c ( e ) f(e)<c(e) f(e)<c(e)
③按路径 P P P上最小剩余容量增加路径流量
④迭代寻找路径 P P P直至无法增加路径流量
例如,在下述所给流网络 G G G中,选择红线路径作为路径 P P P,并增加了11的流量:
如此迭代寻找 P P P,便可以得到解。
但是,显然该方法并不可以得到最优解,例如,当该流网络为如下状态时,
我们发现,按照直观策略,该网络不能再增加流量。但是如果我们稍作调整,
如此,我们便成功将网络的流量增加了1。
我们不妨观察一下,我们做了什么样的改动:我们将流量进行了重新分配,缩减了某些边 ( v 2 , v 3 ) (v_2,v_3) (v2,v3)的流量,并将其重新分配到别的边 ( v 2 , v 4 ) (v_2,v_4) (v2,v4)上,实际上,上述变动可以看作我们沿着下图中红色路径走了1个流量:
也就相当于,我们引入了一条返向边 ( v 3 , v 2 ) (v_3,v_2) (v3,v2),并发现,如果我们寻找路径时允许反向搜索,则可以增大总流量。
一旦引入了反向边,就需要考虑反向边的权重问题,如何定义正向边及反向边的权重以保证流量调整合理呢?做出以下规定:
反向边权重:描述可缩减流量的上限,即原始边上的流量 f ( e ) f(e) f(e)
正向边权重:描述可扩充流量的上限,即原始边上的剩余容量 c ( e ) − f ( e ) c(e)-f(e) c(e)−f(e)
如此,由一条原始边可以生成两条正向、反向边,实现反向搜索,以此来帮助我们更好地寻找到使得总流量增加的路径
P
P
P。
2.2 一些概念
接下来介绍几个概念,并按照上述思路,介绍Ford-Fulkerson算法。
2.2.1 残存网络
对于给定流网络
G
=
<
V
,
E
,
C
>
G=<V,E,C>
G=<V,E,C>和流量
f
f
f,可以得到残存网络
G
f
=
<
V
,
E
f
>
G_f=<V,E_f>
Gf=<V,Ef>,其中
∀
c
f
(
e
)
∈
E
f
\forall c_f(e) \in E_f
∀cf(e)∈Ef,其残存容量为:
c
f
(
e
)
=
{
c
(
e
)
−
f
(
e
)
e
为正向边
f
(
e
)
e
为反向边
c_f(e)=\left\{\begin{matrix}c(e)-f(e) & e为正向边\\ f(e)&e为反向边 \end{matrix}\right.
cf(e)={c(e)−f(e)f(e)e为正向边e为反向边
残存网络中存储的是容量信息(可扩充及可缩减上限),可以帮助我们快速地发现增广路径(包含返向边的路径)。
例如:
2.2.2 增广路径
给定流网络 G = < V , E , C > G=<V,E,C> G=<V,E,C>和流量 f f f,增广路径 p p p是残存网络 G f G_f Gf中一条从源点 s s s到汇点 t t t的简单路径(路径上顶点不重复)。
例如:
如果在残存网络中存在增广路径,则说明存在流量的进一步调整方式。
2.2.3 增广路径的残存容量
增广路径的残存容量指的是一条增广路径 p p p上各边残存容量的最小值,即$c_f§=\min\left { c_f(e)|e\in p \right } $
增广路径的残存容量实际上就是沿着该路径流量扩充的最大值。
2.3 Ford-Fulkerson算法
接下来只需要对我们的只管策略做一些改动,便可以得到Ford-Fulkerson算法:
①对 ∀ e ∈ E \forall e \in E ∀e∈E,初始化流量为 f ( e ) = 0 f(e)=0 f(e)=0
②构造残存网络 G f G_f Gf,寻找源点 s s s到汇点 t t t的增广路径 p p p
③按增广路径 p p p的残存容量增加路径流量
④迭代寻找路径 p p p直至无法增加路径流量
接下来以一个实例来展示该算法:
①流网络 G G G初始化,构造残存网络 G f G_f Gf:
②在残存网络 G f G_f Gf中找到一条增广路径,并按照其容量更新流网络 G G G:
③更新残存网络 G f G_f Gf:
④重复②③:
⑤不能找出增广路径 p p p,算法结束:
2.4 算法分析
该算法的伪代码如下:
复杂度分析:
初始化阶段: O ( E ) O(E) O(E)
寻找增广路径:残存网络最多有 2 E 2E 2E条边,且 O ( V ) ≤ O ( E ) O(V)\leq O(E) O(V)≤O(E),使用DFS,可以在 O ( V + 2 E ) = O ( E ) O(V+2E)=O(E) O(V+2E)=O(E)的时间内找到增广路径
找增广路径残存容量: O ( E ) O(E) O(E)
更新流: O ( E ) O(E) O(E)
每次循环后,流的值至少会增加1,所以循环最多执行 ∣ f ∗ ∣ |f^*| ∣f∗∣次,算法的时间复杂度为 O ( E ∣ f ∗ ∣ ) O(E|f*|) O(E∣f∗∣)文章来源地址https://www.toymoban.com/news/detail-761022.html
实际上,该算法的运行时间主要受限于增广过程,对于同一个流网络 G G G,不同增广路径的选择,会对结果产生巨大的影响,例如:
文章来源:https://www.toymoban.com/news/detail-761022.html
每次循环后,流的值至少会增加1,所以循环最多执行 ∣ f ∗ ∣ |f^*| ∣f∗∣次,算法的时间复杂度为 O ( E ∣ f ∗ ∣ ) O(E|f*|) O(E∣f∗∣)
到了这里,关于【最大流】Ford-Fulkerson算法——算法设计与分析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!