Ford-Fulkerson Algorithm 福特福克森算法
Ford-Fulkerson Algorithm 福特福克森算法
1. 基本思想
Ford-Fulkerson Algorithm 是求解 Maximum Flow 最大流 的经典增广路方法。
核心思想:
从零流开始,只要还能在Residual Network 残量网络中找到一条从源点 到汇点 的路径,就沿这条路径增加流量;当残量网络中不存在 路径时,当前流就是最大流。
形式化地说,给定流网络:
其中:
- :顶点集合;
- :有向边集合;
- :源点 source;
- :汇点 sink;
- :边 的容量 capacity。
算法维护一个流函数 ,满足:
- 容量约束 capacity constraint
- 流量守恒 flow conservation
对任意中间点 :
- 目标函数:最大化流值
一句话总结
Ford-Fulkerson 的本质不是“一次找出最大流”,而是不断在残量网络中找还能继续送流的通道,并逐步增大总流量。
2. 关键概念
2.1 残量容量 Residual Capacity
对于原图中的边 ,如果当前流为 ,容量为 ,则:
正向残量容量
表示边 还能继续增加多少流量。
反向残量容量
表示最多可以撤回多少已经从 送到 的流量。
反向边的意义
反向边不是原网络中真实存在的“管道”,而是一种“撤销机制”。它允许算法修正之前选错的增广路径。
例如,若某条边容量为 ,当前已经送了 单位流:
那么残量网络中有:
含义:还可以正向再送 ,也可以反向撤回 。
2.2 残量网络 Residual Network
残量网络记作:
其中边集合 由所有正残量边组成:
直观理解:
残量网络描述了“在当前流 的基础上,还能怎样调整流量”。
2.3 增广路径 Augmenting Path
一条增广路径是残量网络 中从 到 的简单路径。
设增广路径为:
其瓶颈容量为路径上所有残量容量的最小值:
然后沿路径 增加 单位流。
为什么取最小值?
一条路径能额外送多少流,取决于路径上最窄的那条边。这个最小残量容量就是 bottleneck capacity。
3. 具体过程
Ford-Fulkerson 的过程如下:
- 初始化所有边的流量为 。
- 根据当前流 构造残量网络 。
- 在 中寻找一条从 到 的增广路径 。
- 计算路径瓶颈容量:
- 沿路径 调整流量:
- 如果 是原图正向边,则:
- 如果 是某条原图边 的反向边,则:
- 更新残量网络。
- 重复步骤 3 到步骤 6,直到不存在增广路径。
- 返回当前流 。
终止条件
当残量网络中不存在从 到 的路径时,当前流就是最大流。
4. 伪代码
4.1 主算法
FORD-FULKERSON(G, s, t, c)
for each edge (u, v) in E
f[u, v] <- 0
construct residual network G_f from f
while there exists an augmenting path P from s to t in G_f
delta <- BOTTLENECK(G_f, P)
AUGMENT(f, P, delta)
update residual network G_f
return f
4.2 增广过程
AUGMENT(f, P, delta)
for each edge (u, v) in P
if (u, v) is an original edge
f[u, v] <- f[u, v] + delta
else
// (u, v) is a residual reverse edge
// corresponding original edge is (v, u)
f[v, u] <- f[v, u] - delta
4.3 瓶颈容量
BOTTLENECK(G_f, P)
delta <- +infinity
for each edge (u, v) in P
delta <- min(delta, c_f[u, v])
return delta
5. 正确性依据
5.1 增广路径定理
Ford-Fulkerson 的正确性依赖于增广路径定理:
一个流 是最大流,当且仅当残量网络 中不存在从 到 的增广路径。
即:
证明直觉:
- 如果还有增广路径,就还能继续增加流量,所以不是最大流;
- 如果没有增广路径,则可以在残量网络中把从 可达的点组成集合 ,其余点组成 ,得到一个割 ;
- 这个割的容量等于当前流值;
- 根据 Max-Flow Min-Cut Theorem 最大流最小割定理,当前流为最大流。
5.2 最大流最小割定理
最大流最小割定理说明:
其中 是任意满足 的 - 割。
因此,当某个流 与某个割 满足:
就可以同时证明:
- 是最大流;
- 是最小割。
最优性证书
最大流问题的一个重要优点是:最大流可以用一个等值的最小割作为证书来验证。
6. 时空间复杂度
设:
- :顶点数;
- :边数;
- :最大流值;
- :最大边容量。
6.1 一次增广的代价
如果用 DFS 或 BFS 在残量网络中找一条增广路径,则一次查找代价为:
更新路径上的流量不超过 ,通常被 覆盖。
因此,一次增广的总代价为:
6.2 整数容量时的时间复杂度
如果所有容量都是整数,每次增广至少使流值增加 ,因此增广次数不超过最大流值 。
所以时间复杂度为:
若每条边容量都是 到 之间的整数,则通常可写为:
这不是强多项式时间
Ford-Fulkerson 的复杂度依赖于容量数值 或最大流值 ,而不是只依赖输入规模中的 。因此朴素 Ford-Fulkerson 不是强多项式算法。
6.3 非整数容量时
- 若容量为整数:一定终止。
- 若容量为有理数:经过统一放大为整数后,也能保证终止。
- 若容量为无理数:朴素 Ford-Fulkerson 不保证终止,甚至可能不收敛到最大流。
6.4 空间复杂度
若用邻接表存储原图和残量网络,空间复杂度为:
原因:
- 顶点信息需要 ;
- 原边和对应残量边需要 ;
- BFS/DFS 队列、栈、visited、parent 数组需要 。
7. 需要问题具有的性质
Ford-Fulkerson 适用于满足以下条件的问题:
- 必须能建模为流网络
即有源点 、汇点 、有向边和容量。
- 容量非负
通常要求正容量边才显式存储。
- 流量必须满足容量约束
- 中间顶点满足流量守恒
- 若要保证朴素算法终止,容量最好为整数或有理数
若容量为无理数,路径选择不当时可能出现不终止问题。
- 不同增广路径选择会影响效率
Ford-Fulkerson 本身没有规定如何选增广路径。
常见策略:
- DFS 找任意增广路径:实现简单,但可能很慢;
- BFS 找最短边数增广路径:得到 Edmonds-Karp Algorithm 埃德蒙兹-卡普算法;
- 选瓶颈最大的路径:fat path 思路;
- 容量缩放:Capacity Scaling 容量缩放算法。
8. 典型例子
考虑如下流网络:
flowchart LR
s((s)) -->|3| a((a))
s -->|2| b((b))
a -->|1| b
a -->|2| t((t))
b -->|3| t
边容量如下:
| 边 | 容量 |
|---|---|
| 3 | |
| 2 | |
| 1 | |
| 2 | |
| 3 |
初始时所有边流量为 。
8.1 第一次增广
选择路径:
瓶颈容量:
更新后:
当前流值:
8.2 第二次增广
选择路径:
瓶颈容量:
更新后:
当前流值:
8.3 第三次增广
此时还有路径:
残量容量分别为:
所以瓶颈容量为:
更新后:
当前流值:
8.4 终止与最小割验证
此时从 出发,边 和 都已经满流:
残量网络中已经不存在从 到 的增广路径,所以算法终止。
取割:
割容量为:
当前流值也是:
因此:
根据最大流最小割定理,当前流是最大流,该割是最小割。
9. 易错点
易错点 1:把 Ford-Fulkerson 当成一个固定算法
Ford-Fulkerson 更像一个“方法框架”。它只要求不断找增广路径,但没有规定具体用 DFS、BFS 还是其他策略。
易错点 2:忽略反向边
如果没有反向边,算法无法撤销之前的错误选择,就可能像普通贪心一样卡在非最优解。
易错点 3:以为无增广路径只是“局部最优”
在最大流问题中,无增广路径不是局部最优,而是全局最优的充要条件。
易错点 4:混淆容量和流量
容量 是上限;流量 是当前实际通过的量;残量 是还能调整的量。
10. 与相关算法的关系
| 算法 | 增广路径选择方式 | 时间复杂度特点 |
|---|---|---|
| Ford-Fulkerson | 任意增广路径 | $O(m |
| Edmonds-Karp | BFS 选最少边数增广路径 | |
| Capacity Scaling | 优先使用大残量路径 | 或相关改进形式 |
| Dinic | 分层图 + 阻塞流 | 通常优于朴素增广路法 |
记忆方式
Ford-Fulkerson 是“增广路思想”;Edmonds-Karp 是“用 BFS 选增广路”的 Ford-Fulkerson 特例。
11. 最小实现思路
若用程序实现,通常维护:
- 邻接表
graph[u]; - 每条边的
to、capacity、rev; - 反向边用于更新残量;
- BFS/DFS 找增广路径;
- 沿 parent 数组回溯路径并更新残量。
伪代码层面可以写成:
while path exists from s to t in residual graph
delta <- minimum residual capacity on path
for each edge on path
decrease forward residual capacity by delta
increase reverse residual capacity by delta
max_flow <- max_flow + delta
12. 复习问题
- 为什么 Ford-Fulkerson 需要残量网络?
- 反向边为什么表示“撤销”而不是实际新增一条边?
- 为什么瓶颈容量决定一次增广能增加多少流?
- 为什么没有增广路径时,当前流一定是最大流?
- Ford-Fulkerson 和 Edmonds-Karp 的区别是什么?
13. References
- Cormen, Thomas H.; Leiserson, Charles E.; Rivest, Ronald L.; Stein, Clifford. Introduction to Algorithms, 3rd edition. Chapter 26: Maximum Flow.
- Wayne, Kevin. Network Flow I. Princeton / Kleinberg-Tardos lecture slides.
- Ford, L. R.; Fulkerson, D. R. 1956. Maximal Flow Through a Network. Canadian Journal of Mathematics.
- Elias, P.; Feinstein, A.; Shannon, C. E. 1956. A Note on the Maximum Flow Through a Network. IRE Transactions on Information Theory.