无向图的最大流问题(Edmonds-Karp 算法在有向图中的扩展与应用)
字数 3493 2025-12-13 19:22:29

无向图的最大流问题(Edmonds-Karp 算法在有向图中的扩展与应用)


题目描述

给定一个无向图 \(G = (V, E)\) ,其中每条边 \(e\) 有一个整数容量 \(c(e) \ge 0\)。指定一个源点 \(s\) 和一个汇点 \(t\),求从 \(s\)\(t\) 的最大流。
注意:在无向图中,每条边允许流量双向通过,但流量总和不能超过该边的容量。

示例

无向图:
       (2)
      /   \
     /     \
   s---(3)---t

边上的数字为容量,例如边 (s, 2) 容量为 2,边 (2, t) 容量为 2,边 (s, t) 容量为 3。
最大流值是多少?


解题过程循序渐进讲解

第一步:理解无向图最大流与有向图的区别

在有向图中,每条有向边有方向,流量只能从尾部流向头部。
无向图中,每条边相当于双向都有相同容量的管道。但总流量不能超过容量,这意味着如果在一个方向上流了 \(x\) 单位,另一个方向上就不能流超过 \(c - x\) 单位(否则总流量超过容量)。

关键思路:将无向边转化为两条方向相反的有向边,每条有向边容量等于原无向边的容量。
转化后,我们得到一个有向图,然后应用经典的最大流算法(如 Edmonds-Karp)求解。


第二步:无向边转化为有向边

对于每条无向边 \((u, v)\) 容量 \(c\)

  • 添加有向边 \(u \to v\),容量 \(c\)
  • 添加有向边 \(v \to u\),容量 \(c\)

为什么这样转化是正确的?
假设在无向边上,从 \(u\)\(v\) 流了 \(f_{uv}\),从 \(v\)\(u\) 流了 \(f_{vu}\)。无向边的限制是:

\[f_{uv} + f_{vu} \le c \]

在转化后的有向图中,有两条有向边:

  • \(u \to v\) 上流了 \(f_{uv}\)(正向),其剩余容量为 \(c - f_{uv}\)
  • \(v \to u\) 上流了 \(f_{vu}\)(正向),其剩余容量为 \(c - f_{vu}\)

注意,如果我们想在 \(u \to v\) 方向增加流量 \(\Delta\),需要检查有向边 \(u \to v\) 的剩余容量 \(c - f_{uv}\) 是否足够,这与无向边限制 \(f_{uv} + f_{vu} \le c\) 一致。
类似地,在 \(v \to u\) 方向增加流量,检查另一条有向边容量。
因此这种转化完美模拟了无向边的容量约束。


第三步:应用 Edmonds-Karp 算法

Edmonds-Karp 是 Ford-Fulkerson 方法的一种,使用 BFS 寻找最短增广路(按边数最少),复杂度 \(O(VE^2)\)
在有向图上运行 Edmonds-Karp 的步骤:

  1. 初始化:创建有向图(如上转化),设置所有边的流量为 0。
  2. BFS 找增广路:在剩余网络中,从 \(s\) 出发 BFS 寻找一条到 \(t\) 的路径,要求每条边剩余容量 > 0。
  3. 计算瓶颈容量:在找到的路径上,最小剩余容量值 \(\Delta\) 为该增广路可增加的流量。
  4. 更新流量
    • 对于路径上的每条有向边 \(u \to v\),流量增加 \(\Delta\)
    • 同时,反向边 \(v \to u\) 的流量减少 \(\Delta\)(反向边初始容量为 0,流量可为负,表示正向剩余容量增加)。
  5. 重复步骤 2-4 直到无法找到 \(s\)\(t\) 的增广路。
  6. 最大流值 = 从 \(s\) 流出的总流量。

注意:反向边的初始容量为 0,但在更新流量时,我们允许减少正向边的流量(通过反向边流“负流量”实现),这是 Ford-Fulkerson 方法的通用技巧,用来撤销之前分配的流量。


第四步:示例计算

示例图(无向):
顶点:\(s, 2, t\)
边:

  • \(e1: (s,2), c=2\)
  • \(e2: (2,t), c=2\)
  • \(e3: (s,t), c=3\)

转化为有向图
边:

  1. \(s \to 2\), cap=2
  2. \(2 \to s\), cap=2
  3. \(2 \to t\), cap=2
  4. \(t \to 2\), cap=2
  5. \(s \to t\), cap=3
  6. \(t \to s\), cap=3

初始流量均为 0。

第一次 BFS:可能路径 \(s \to t\),瓶颈容量 = 3。
更新:

  • \(s \to t\) 流量 = 3,剩余容量 = 0。
  • 反向边 \(t \to s\) 流量 = -3(相当于剩余容量 3 增加 3 变为 6,但实际我们只记录流量,剩余容量 = 初始容量 - 流量)。

剩余网络(只画剩余容量 >0 的边):

  • \(s \to 2\), res=2
  • \(2 \to s\), res=2
  • \(2 \to t\), res=2
  • \(t \to 2\), res=2
  • \(t \to s\), res=3(因为反向边,初始 3 减去流量 -3 得 6,但这里注意:我们通常记录正向边的剩余容量,但算法中直接存流量值然后计算剩余容量)

我们用标准剩余图表示:

  • 对边 \(s\to t\) 流量=3,cap=3 → 剩余容量=0,反向边剩余容量=3。
  • 对边 \(t\to s\) 是另一条有向边,cap=3,流量=0 → 剩余容量=3。

但为了清晰,我们直接列出所有有向边的剩余容量(res = cap - flow):

  1. \(s\to 2\): flow=0, res=2
  2. \(2\to s\): flow=0, res=2
  3. \(2\to t\): flow=0, res=2
  4. \(t\to 2\): flow=0, res=2
  5. \(s\to t\): flow=3, res=0
  6. \(t\to s\): flow=0, res=3

第二次 BFS:路径 \(s \to 2 \to t\)

  • \(s\to 2\) res=2
  • \(2\to t\) res=2
    瓶颈容量 = 2。

更新:

  • \(s\to 2\) 流量 += 2 → flow=2, res=0
  • \(2\to t\) 流量 += 2 → flow=2, res=0
  • 反向边 \(2\to s\) 流量 -= 2 → flow=-2, res=4
  • 反向边 \(t\to 2\) 流量 -= 2 → flow=-2, res=4

第三次 BFS
剩余容量 >0 的边:

  • \(2\to s\) res=4
  • \(t\to 2\) res=4
  • \(t\to s\) res=3
  • \(s\to t\) res=0 等

但注意:我们可以走 \(s \to t\) 吗?剩余容量 0,不行。
我们可以走 \(s \to 2\) 吗?剩余容量 0,不行。
从 s 出发没有边到任何点有剩余容量(因为 s 出发的边:s→2 res=0, s→t res=0),所以 BFS 找不到路径,算法停止。

总流量 = 第一次 3 + 第二次 2 = 5。

检查合理性:
原无向图最大流应为:

  • 直接边 s-t 流 3
  • 路径 s-2-t 流 2
    总 5,与算法结果一致。

第五步:算法正确性证明简述

因为我们把无向图转化为有向图后,任何在无向图中的可行流对应到有向图中,可以分配流量到两条有向边上,使得满足容量约束;反之,有向图中找到的流也能映射回无向图,且满足无向边总流量 ≤ 容量。
因此,求转化后有向图的最大流就是原无向图的最大流。


第六步:时间复杂度

转化后边数 \(2|E|\),所以 \(E' = 2E\),顶点数 \(V\) 不变。
Edmonds-Karp 复杂度 \(O(VE^2)\) 中的 E 是转化后的有向边数,所以是 \(O(V(2E)^2) = O(VE^2)\)(常数因子忽略)。


最终答案
无向图最大流可以通过将每条无向边替换为两条相反的有向边,然后使用 Edmonds-Karp 等最大流算法求解,方法与有向图相同。

无向图的最大流问题(Edmonds-Karp 算法在有向图中的扩展与应用) 题目描述 给定一个 无向图 \( G = (V, E) \) ,其中每条边 \( e \) 有一个 整数容量 \( c(e) \ge 0 \)。指定一个源点 \( s \) 和一个汇点 \( t \),求从 \( s \) 到 \( t \) 的最大流。 注意:在无向图中,每条边允许流量双向通过,但流量总和不能超过该边的容量。 示例 边上的数字为容量,例如边 (s, 2) 容量为 2,边 (2, t) 容量为 2,边 (s, t) 容量为 3。 最大流值是多少? 解题过程循序渐进讲解 第一步:理解无向图最大流与有向图的区别 在有向图中,每条有向边有方向,流量只能从尾部流向头部。 在 无向图 中,每条边相当于 双向都有相同容量 的管道。但总流量不能超过容量,这意味着如果在一个方向上流了 \( x \) 单位,另一个方向上就不能流超过 \( c - x \) 单位(否则总流量超过容量)。 关键思路 :将无向边转化为两条方向相反的 有向边 ,每条有向边容量等于原无向边的容量。 转化后,我们得到一个有向图,然后应用经典的最大流算法(如 Edmonds-Karp)求解。 第二步:无向边转化为有向边 对于每条无向边 \( (u, v) \) 容量 \( c \): 添加有向边 \( u \to v \),容量 \( c \)。 添加有向边 \( v \to u \),容量 \( c \)。 为什么这样转化是正确的? 假设在无向边上,从 \( u \) 到 \( v \) 流了 \( f_ {uv} \),从 \( v \) 到 \( u \) 流了 \( f_ {vu} \)。无向边的限制是: \[ f_ {uv} + f_ {vu} \le c \] 在转化后的有向图中,有两条有向边: 边 \( u \to v \) 上流了 \( f_ {uv} \)(正向),其剩余容量为 \( c - f_ {uv} \)。 边 \( v \to u \) 上流了 \( f_ {vu} \)(正向),其剩余容量为 \( c - f_ {vu} \)。 注意,如果我们想在 \( u \to v \) 方向增加流量 \( \Delta \),需要检查有向边 \( u \to v \) 的剩余容量 \( c - f_ {uv} \) 是否足够,这与无向边限制 \( f_ {uv} + f_ {vu} \le c \) 一致。 类似地,在 \( v \to u \) 方向增加流量,检查另一条有向边容量。 因此这种转化完美模拟了无向边的容量约束。 第三步:应用 Edmonds-Karp 算法 Edmonds-Karp 是 Ford-Fulkerson 方法的一种,使用 BFS 寻找最短增广路(按边数最少),复杂度 \( O(VE^2) \)。 在有向图上运行 Edmonds-Karp 的步骤: 初始化 :创建有向图(如上转化),设置所有边的流量为 0。 BFS 找增广路 :在 剩余网络 中,从 \( s \) 出发 BFS 寻找一条到 \( t \) 的路径,要求每条边剩余容量 > 0。 计算瓶颈容量 :在找到的路径上,最小剩余容量值 \( \Delta \) 为该增广路可增加的流量。 更新流量 : 对于路径上的每条有向边 \( u \to v \),流量增加 \( \Delta \)。 同时,反向边 \( v \to u \) 的流量减少 \( \Delta \)(反向边初始容量为 0,流量可为负,表示正向剩余容量增加)。 重复步骤 2-4 直到无法找到 \( s \) 到 \( t \) 的增广路。 最大流值 = 从 \( s \) 流出的总流量。 注意 :反向边的初始容量为 0,但在更新流量时,我们允许减少正向边的流量(通过反向边流“负流量”实现),这是 Ford-Fulkerson 方法的通用技巧,用来撤销之前分配的流量。 第四步:示例计算 示例图(无向): 顶点:\( s, 2, t \) 边: \( e1: (s,2), c=2 \) \( e2: (2,t), c=2 \) \( e3: (s,t), c=3 \) 转化为有向图 : 边: \( s \to 2 \), cap=2 \( 2 \to s \), cap=2 \( 2 \to t \), cap=2 \( t \to 2 \), cap=2 \( s \to t \), cap=3 \( t \to s \), cap=3 初始流量均为 0。 第一次 BFS :可能路径 \( s \to t \),瓶颈容量 = 3。 更新: 边 \( s \to t \) 流量 = 3,剩余容量 = 0。 反向边 \( t \to s \) 流量 = -3(相当于剩余容量 3 增加 3 变为 6,但实际我们只记录流量,剩余容量 = 初始容量 - 流量)。 剩余网络 (只画剩余容量 >0 的边): \( s \to 2 \), res=2 \( 2 \to s \), res=2 \( 2 \to t \), res=2 \( t \to 2 \), res=2 \( t \to s \), res=3(因为反向边,初始 3 减去流量 -3 得 6,但这里注意:我们通常记录正向边的剩余容量,但算法中直接存流量值然后计算剩余容量) 我们用标准剩余图表示: 对边 \( s\to t \) 流量=3,cap=3 → 剩余容量=0,反向边剩余容量=3。 对边 \( t\to s \) 是另一条有向边,cap=3,流量=0 → 剩余容量=3。 但为了清晰,我们直接列出所有有向边的剩余容量(res = cap - flow): \( s\to 2 \): flow=0, res=2 \( 2\to s \): flow=0, res=2 \( 2\to t \): flow=0, res=2 \( t\to 2 \): flow=0, res=2 \( s\to t \): flow=3, res=0 \( t\to s \): flow=0, res=3 第二次 BFS :路径 \( s \to 2 \to t \): \( s\to 2 \) res=2 \( 2\to t \) res=2 瓶颈容量 = 2。 更新: \( s\to 2 \) 流量 += 2 → flow=2, res=0 \( 2\to t \) 流量 += 2 → flow=2, res=0 反向边 \( 2\to s \) 流量 -= 2 → flow=-2, res=4 反向边 \( t\to 2 \) 流量 -= 2 → flow=-2, res=4 第三次 BFS : 剩余容量 >0 的边: \( 2\to s \) res=4 \( t\to 2 \) res=4 \( t\to s \) res=3 \( s\to t \) res=0 等 但注意:我们可以走 \( s \to t \) 吗?剩余容量 0,不行。 我们可以走 \( s \to 2 \) 吗?剩余容量 0,不行。 从 s 出发没有边到任何点有剩余容量(因为 s 出发的边:s→2 res=0, s→t res=0),所以 BFS 找不到路径,算法停止。 总流量 = 第一次 3 + 第二次 2 = 5。 检查合理性: 原无向图最大流应为: 直接边 s-t 流 3 路径 s-2-t 流 2 总 5,与算法结果一致。 第五步:算法正确性证明简述 因为我们把无向图转化为有向图后,任何在无向图中的可行流对应到有向图中,可以分配流量到两条有向边上,使得满足容量约束;反之,有向图中找到的流也能映射回无向图,且满足无向边总流量 ≤ 容量。 因此,求转化后有向图的最大流就是原无向图的最大流。 第六步:时间复杂度 转化后边数 \( 2|E| \),所以 \( E' = 2E \),顶点数 \( V \) 不变。 Edmonds-Karp 复杂度 \( O(VE^2) \) 中的 E 是转化后的有向边数,所以是 \( O(V(2E)^2) = O(VE^2) \)(常数因子忽略)。 最终答案 : 无向图最大流可以通过 将每条无向边替换为两条相反的有向边 ,然后使用 Edmonds-Karp 等最大流算法求解,方法与有向图相同。