Skip to content

Edmonds-Karp 算法:最大流

🎯 本节目标: 掌握 Edmonds-Karp 算法原理、BFS 增广路搜索与 MoonBit 实现 | ⏱️ 预计阅读时间: 10 分钟

Edmonds-Karp 算法是 Ford-Fulkerson 方法的一个具体实现,由 Jack Edmonds 和 Richard Karp 于 1972 年提出。与通用 Ford-Fulkerson 框架不同,Edmonds-Karp 使用 BFS 寻找最短增广路(边数最少),从而保证多项式时间复杂度 O(VE²)。

算法在残差图上反复执行 BFS:从源点出发,沿着有剩余容量的边搜索到汇点的路径,找到瓶颈容量后推送流量并更新反向边——“反悔”机制允许后续迭代撤销之前的流量分配。

颜色/状态含义
橙色当前 BFS 搜索路径
绿色已推送流量的边
红色饱和边(流量 = 容量)
虚线反向边(残差)

核心代码来自 lib/algo/flow/edmonds_karp.mbt。算法使用 FlowNetwork 独立类型(非 GraphReadable 实现),包含容量矩阵和流量矩阵。

///|
/// Edmonds-Karp 最大流算法
/// 时间复杂度 O(VE²),空间复杂度 O(V²)
pub fn edmonds_karp(
graph : FlowNetwork,
source : Int,
sink : Int,
) -> MaxFlowResult {
let n = graph.node_count()
let capacity = graph.capacity_matrix() // 容量矩阵
let flow = deep_copy_matrix(graph.flow_matrix()) // 深拷贝保持纯函数
let mut max_flow = 0.0
let mut iter_count = 0
while true {
// BFS 寻找最短增广路
let parent : Array[Int?] = Array::make(n, None)
let visited : Array[Bool] = Array::make(n, false)
let queue : Array[Int] = [source]
visited[source] = true
let mut head = 0
let mut found = false
while head < queue.length() && !found {
let u = queue[head]; head = head + 1
let mut v = 0
while v < n {
if !visited[v] && capacity[u][v] - flow[u][v] > 0.000001 {
visited[v] = true
parent[v] = Some(u)
if v == sink { found = true; break }
queue.push(v)
}
v = v + 1
}
}
if !found { break } // 无可增广路
// 计算瓶颈容量
let mut bottleneck = 1000000000000000000.0
let mut cur = sink
while true {
match parent[cur] {
None => break
Some(p) => {
let residual = capacity[p][cur] - flow[p][cur]
if residual < bottleneck && residual > 0.0 { bottleneck = residual }
cur = p
}
}
}
// 沿路径增广
cur = sink
while cur != source {
match parent[cur] {
None => break
Some(p) => {
flow[p][cur] = flow[p][cur] + bottleneck
flow[cur][p] = flow[cur][p] - bottleneck // 反向边
cur = p
}
}
}
max_flow = max_flow + bottleneck
iter_count = iter_count + 1
}
MaxFlowResult::{ max_flow, flow_matrix: flow, iteration_count: iter_count }
}

为什么深度复制流量矩阵? 保证纯函数语义:多次调用算法不会相互影响。虽然增加了 O(V²) 开销,但避免了对输入网络的副作用。

fn edmonds_karp_demo() -> Unit {
let net = FlowNetwork::new(4)
let net = net.add_edge(0, 1, 10.0)
let net = net.add_edge(0, 2, 5.0)
let net = net.add_edge(1, 2, 6.0)
let net = net.add_edge(1, 3, 8.0)
let net = net.add_edge(2, 3, 9.0)
let result = @flow.edmonds_karp(net, 0, 3)
println("最大流量: \{result.max_flow\}")
println("迭代次数: \{result.iteration_count\}")
}
  • 交通流量优化:道路网的车辆最大通行能力分析
  • 供水管网调度:水源到城区的水流量最大化
  • 二分图匹配:最大流可规约为二分图最大匹配(增加超级源汇)