xxx 最小费用最大流问题(Successive Shortest Path with Potentials 算法)
字数 2173 2025-11-06 12:40:14
xxx 最小费用最大流问题(Successive Shortest Path with Potentials 算法)
题目描述
给定一个带权有向图 \(G = (V, E)\),每条边 \((u, v)\) 有容量 \(c(u, v) > 0\) 和单位流量的费用 \(a(u, v)\)。图中包含源点 \(s\) 和汇点 \(t\)。目标是找到从 \(s\) 到 \(t\) 的最大流,且总费用最小(总费用定义为所有边上的流量乘以单位费用之和)。
解题过程
-
问题分析
- 在最大流的基础上增加费用最小化的目标,需同时优化流量和费用。
- 核心思路:在残余网络中反复寻找从 \(s\) 到 \(t\) 的最短路径(按费用计算),并沿该路径推送尽可能多的流量,逐步逼近最小费用最大流。
-
基础算法:Successive Shortest Path (SSP)
- 步骤1:初始化流量 \(f(u, v) = 0\),残余容量 \(r(u, v) = c(u, v)\)。
- 步骤2:在残余网络 \(G_f\) 中,边 \((u, v)\) 的权重为:
- 若原边有剩余容量(\(r(u, v) > 0\)),权重为 \(a(u, v)\);
- 若反向边有流量(\(f(v, u) > 0\)),则添加反向边 \((v, u)\),权重为 \(-a(u, v)\)。
- 步骤3:用 Bellman-Ford 算法计算从 \(s\) 到所有顶点的最短路径(按费用),避免负权环的影响。
- 步骤4:若存在从 \(s\) 到 \(t\) 的路径,则沿该路径推送最大可能流量(路径上最小残余容量),更新流量和残余网络。
- 步骤5:重复步骤2-4,直到无法从 \(s\) 到达 \(t\)。
-
优化:引入势能函数(Potentials)
- 问题:残余网络中可能出现负权边,直接使用 Dijkstra 算法会失效。
- 解决方案:通过势能函数 \(p(v)\) 调整边权,使所有边权非负。
- 势能函数定义:对于任意边 \((u, v)\),满足 \(a(u, v) + p(u) - p(v) \geq 0\)。
- 初始势能:通过 Bellman-Ford 计算从 \(s\) 到各点的最短路径距离 \(d(v)\),令 \(p(v) = d(v)\)。
- 调整边权:将边 \((u, v)\) 的权重改为 \(a_p(u, v) = a(u, v) + p(u) - p(v)\)。
- 性质:调整后所有边权非负,且路径费用差不变(仅整体偏移一个常数),因此最短路径保持不变。
-
算法步骤(SSP with Potentials)
- 初始化:
- 设置流量 \(f = 0\),势能 \(p(v) = 0\)(或通过 Bellman-Ford 初始化)。
- 在残余网络 \(G_f\) 中,若存在负权边,用 Bellman-Ford 计算初始 \(p(v)\)。
- 循环直到无法增广:
- 根据当前势能 \(p\),构建调整权重后的残余网络 \(G_f'\)(边权为 \(a_p\))。
- 在 \(G_f'\) 上运行 Dijkstra 算法,求从 \(s\) 到 \(t\) 的最短路径 \(P\)。
- 若路径不存在,终止算法;否则沿 \(P\) 推送流量 \(\delta = \min\{ r(u, v) \mid (u, v) \in P \}\)。
- 更新流量和残余容量:
- 对于正向边:\(f(u, v) \leftarrow f(u, v) + \delta\),\(r(u, v) \leftarrow r(u, v) - \delta\)。
- 对于反向边:\(r(v, u) \leftarrow r(v, u) + \delta\)。
- 更新势能:\(p(v) \leftarrow p(v) + d(v)\),其中 \(d(v)\) 是本次 Dijkstra 计算的最短距离。
- 初始化:
-
正确性关键
- 势能更新确保调整后的边权始终非负,允许使用高效的 Dijkstra 算法。
- 每次增广的路径是当前残余网络中费用最小的路径,保证最终解是最优的。
-
复杂度分析
- 使用 Bellman-Ford 初始化:\(O(VE)\)。
- 每次增广使用 Dijkstra:若用二叉堆,为 \(O(E \log V)\)。
- 最多增广 \(O(\text{最大流值})\) 次,总复杂度为 \(O(F \cdot E \log V)\),其中 \(F\) 是最大流值。
示例说明
假设一个简单网络:边 \((s, u)\) 容量 2、费用 1;边 \((u, t)\) 容量 2、费用 1;边 \((s, t)\) 容量 1、费用 3。
- 初始势能 \(p = 0\),第一次 Dijkstra 找到路径 \(s \to u \to t\)(费用 2),推送流量 2,总费用 4。
- 残余网络中边 \((s, t)\) 费用 3 仍较高,算法终止,得到最小费用最大流。