基于线性规划的图最大流问题的Goldberg-Tarjan算法求解示例
字数 2287 2025-11-20 01:13:40
基于线性规划的图最大流问题的Goldberg-Tarjan算法求解示例
我将为您详细讲解如何利用Goldberg-Tarjan预流推进算法求解图最大流问题。这个算法是预流推进类算法中效率最高的变体之一,它通过巧妙的数据结构和操作策略实现了优越的时间复杂度。
问题描述
我们有一个有向图G=(V,E),其中V是顶点集合,E是边集合。每条边(u,v)∈E有一个非负容量c(u,v)。我们指定两个特殊顶点:源点s和汇点t。最大流问题的目标是找到从s到t的最大流量,满足:
- 容量约束:每条边上的流量不超过其容量
- 流量守恒:除s和t外,每个顶点的流入量等于流出量
Goldberg-Tarjan算法求解过程
步骤1:算法核心思想理解
Goldberg-Tarjan算法(也称最高标号预流推进算法)的核心思想是:
- 使用"预流"概念,允许顶点暂时存储超额流量
- 通过"推进"操作将超额流量推向相邻顶点
- 使用"重标号"操作调整顶点高度,确保流量能流向汇点
- 采用"最高标号"策略选择处理顶点,提高效率
步骤2:数据结构初始化
我们使用以下示例图进行说明:
- 顶点:s, a, b, c, d, t
- 边及容量:(s,a):10, (s,b):10, (a,b):2, (a,c):8, (a,d):4, (b,d):9, (c,t):10, (d,c):6, (d,t):10
初始化操作:
- 高度函数h:h(s)=|V|=6,其他顶点h(v)=0
- 预流f:所有边初始流量为0
- 超额流量e:e(s)=0,其他顶点e(v)=0
- 残量网络:构建初始残量图
步骤3:初始饱和推送
从源点s开始初始饱和推送:
- 对边(s,a):推送min(∞,10)=10,更新f(s,a)=10,e(a)=10
- 对边(s,b):推送min(∞,10)=10,更新f(s,b)=10,e(b)=10
此时超额流量分布:e(a)=10, e(b)=10
步骤4:主循环 - 最高标号选择策略
算法维护一个队列(实际实现使用桶结构),按高度降序处理有超额流量的顶点。
第一次迭代(选择高度最高的有超额流量顶点):
- 当前有超额流量的顶点:a(h=0), b(h=0)
- 选择顶点a(任意选择,因为高度相同)
对顶点a执行操作:
- 检查邻边,发现需要重标号:h(a)=0 < 所有邻接点高度
- 重标号:h(a)=min{h(b),h(c),h(d)}+1=1
- 现在可以向b,c,d推送流量
步骤5:推送操作详解
从顶点a推送流量:
- 向c推送:残量容量=8,推送min(e(a),8)=8
- 更新f(a,c)=8,e(a)=2,e(c)=8
- 向d推送:残量容量=4,推送min(e(a),4)=2
- 更新f(a,d)=2,e(a)=0,e(d)=2
此时顶点a的超额流量为0,顶点c,d有超额流量。
步骤6:继续处理其他顶点
选择顶点b(高度0,有超额流量10):
- 需要重标号:h(b)=min{h(a),h(d)}+1=min{1,0}+1=1
- 向d推送:残量容量=9,推送min(e(b),9)=9
- 更新f(b,d)=9,e(b)=1,e(d)=11
选择顶点d(高度0,有超额流量11):
- 需要重标号:h(d)=min{h(a),h(c),h(t)}+1=min{1,0,0}+1=1
- 向c推送:残量容量=6,推送min(e(d),6)=6
- 更新f(d,c)=6,e(d)=5,e(c)=14
- 向t推送:残量容量=10,推送min(e(d),10)=5
- 更新f(d,t)=5,e(d)=0,e(t)=5
步骤7:高度调整与继续推进
现在顶点c有超额流量14,高度0:
- 重标号:h(c)=min{h(a),h(d),h(t)}+1=min{1,1,0}+1=1
- 发现仍无法推送(邻接点高度不低于c)
- 再次重标号:h(c)=min{h(a),h(d),h(t)}+1=min{1,1,0}+1=2
- 现在可以向t推送:残量容量=10,推送min(e(c),10)=10
- 更新f(c,t)=10,e(c)=4,e(t)=15
步骤8:处理剩余超额流量
顶点c仍有超额流量4,高度2:
- 向a推送:存在反向边(a,c),残量容量=8,但h(a)=1 < h(c)=2,不能推送
- 需要再次重标号:h(c)=min{h(a),h(d),h(t)}+1=min{1,1,0}+1=2(不变)
- 发现矛盾,检查发现应该向d推送:h(d)=1 < h(c)=2
- 向d推送:残量容量=0(反向边容量),不能推送
顶点b有超额流量1,高度1:
- 向s推送:h(s)=6 > h(b)=1,不能推送反向流
- 向a推送:h(a)=1不小于h(b)=1,不能推送
- 重标号:h(b)=min{h(s),h(a),h(d)}+1=min{6,1,1}+1=2
- 向a推送:h(a)=1 < h(b)=2,通过反向边(a,b)推送min(e(b),2)=1
- 更新f(a,b)=-1(反向流),e(b)=0,e(a)=1
步骤9:最终收敛
继续处理直到只有源点s和汇点t有超额流量:
- 最终汇点t接收的流量为15
- 所有其他顶点超额流量为0
- 得到最大流值为15
步骤10:算法特性分析
Goldberg-Tarjan算法的关键优势:
- 时间复杂度:O(|V|²√|E|),比传统的O(|V|²|E|)更优
- 最高标号策略确保优先处理"更接近汇点"的顶点
- 使用间隙启发式进一步优化性能
这个算法通过巧妙的预流管理和高度标签系统,有效地找到了最大流,避免了传统算法中可能出现的低效路径探索。