最短路径常见应用场景:加权无向图最短路径、给定两点的最短路径、加权有向无环图的最长路径、并行任务调度、负权重环检测、套汇等等。
加权无向图最短路径
将无向图看成有向图,利用有向图的算法来计算最短路径。
- 转换
给定的加权无向图,创建一幅由相同顶点构成的加权有向图,且对于无向图中的每条边,相应地创建两条(方向不同)有向边。有向图中的路径和无向图中的路径存在一一对应的关系,路径的权重也是相同的;所以最短路径问题是等价的。 - 特点
权值不能为负值,否则在创建对应有向图时,每两个顶点间都存在一个负权重环。
给定两点的最短路径
给定一幅加权有向图,以及一个起点 s
和一个终点 t
,找到 s
到 t
的最短路径。
如果不包含负权重,可以在 Dijkstra
算法中,从优先队列取出目标顶点 t
之后终止搜索,而 distTo[t]
则为最短路径值。
1 | public DijkstraSP(EdgeWeightedDigraph G, int s) { |
加权有向无环图的最长路径
给定一幅无环加权有向图和起点 s
,是否存在一条 s
到给定顶点 v
的路径?找出最长(总权重最大)的路径。
算法一:转换为最短路径
复制原始无环加权有向图得到一个副本,并将副本中所有边的权重变为负值。计算副本中的最短路径,即为原图中的最长路径。
算法二:修改最短路径判断条件
修改最短路径算法,初始化时将 distTo[]
为负无穷,放松边时判断 distTo[w] < distTo[v] + e.weight()
,这样就称为最长路径算法了。
1 | public AcyclicLP(EdgeWeightedDigraph G, int s) { |
并行任务调度
优先级限制下的并行任务调度:给定一组需要完成的特定任务,以及一组关于任务完成的先后次序的优先级限制!在满足限制条件的前提下,应该如何在若干相同处理器上安排任务,并在最短时间内完成所有任务?
关键路径:并行任务序列中,耗时最长路径即为关键路径。可以证明:关键路径和无环加权有向图的最长路径问题是等价的。
解决关键路径步骤
解决并行任务调度的关键路径的方法步骤如下:
- 创建一幅无环加权有向图,其中包含起点
s
和终点t
,并且每个任务都对应两个顶点(任务起始顶点和任务结束顶点)。也就是说N
个任务的无环加权有向图中,一共有2*N+2
个顶点。其中2*N
表示为图的起点,2*N+1
为图的终点,i
为任务起始顶点,i+N
为任务的结束顶点 - 每个任务都有一条从它的起始顶点到结束顶点的边,边的权重即为任务所需时间
- 对于每条优先级限制
v-w
,添加一条从v
的结束顶点指向w
的起始顶点的边,并设定权重为零 - 为每个任务添加一条从图的起点
s
指向任务的起始顶点的边,并设定权重为零 - 为每个任务添加一条从任务的结束顶点指向图的终点
t
的边,并设定权重为零 - 这样每个任务预计的开始时间:为图的起点
s
到任务的起始顶点的最长距离 - 并行任务调度的关键路径为:图的起点
s
到图的终点t
的最长距离
并行任务调度转换为:无环加权有向图的最长路径。
测试数据
并行任务调度数据:
1 | $ more jobPC.txt |
测试数据共有 10 个任务,其中第七行数据 21.0 2 3 8
表示:任务 7 的耗时为 21.0,有 2 个前置任务;任务 7 必须在任务 3,8 两个前置任务之前完成。数据对应的是上面的示例图。
算法分析
1 | public class CPM { |
测试结果
1 | % java CPM < jobsPC.txt |
负权重环检测
Bellman-Ford
算法包含了负权重环的检测,可以使用该算法来计算最短路径并判断是否存在负权重环。
套汇
套汇问题等价于加权有向图中的负权重环的检测问题。
转换步骤
取每条边权重的自然对数并取反,这样套汇问题中的权重之积的计算转换为新图中的所有边权重之和的计算。任意权重之积 w1*w2*...wk
即对应 -lnw1-lnw2...-lnwk
之和。转换后边的权重可能为正也可能为负,一条从 v
到 w
的路径表示将货币 v
兑换为货币 w
,任意负权重环都是一次套汇机会。
测试数据
套汇测试数据各种货币汇率:
1 | % more rates.txt |
第一行数据 USD 1 0.741 0.657 1.061 1.005
表示:当前顶点代表美元 USD
,兑换其他四种货币的汇率分别为 0.741 0.657 1.061 1.005
。
算法解析
1 | public class Arbitrage { |
测试结果
1 | % java Arbitrage < rates.txt |
表示存在负权重环,有套现机会。套现路径为:USD -> EUR -> CAD -> USD
,即 1000 美元经过套汇后,能获取 1007 美元。
参考文档
- 《算法:第四版》 第 4 章