找到图中两点之间的最短路径是一个经典的算法问题,有许多好的答案(Dijkstra's algorithm,Bellman-Ford等) . 我的问题是,在给定有向加权图的情况下,是否存在一个有效的算法,一对节点s和t,以及值k,找到s和t之间的第k个最短路径 . 如果有多条相同长度的路径都与第k个最短路径相关,那么算法返回任何路径都是正常的 .
我怀疑这个算法可能可以在多项式时间内完成,但我知道可能会减少longest path problem会使NP难以实现 .
有没有人知道这样的算法,或者表明它是NP难的减少?
4 回答
根据可用的Kth最短路径算法,Yen的算法是最容易理解的 . 大多数情况下,这是因为Yen算法首先需要计算所有K-1最短路径才能计算出Kth最短路径,因此可以将其分解为子问题 .
此外,由于每个子问题使用标准的最短路径算法(例如Dijkstra’s algorithm),因此从第1个最短路径问题到第K个最短路径问题是更自然的扩展 .
以下是在具有等权边的示例图中查找第3条最短路径的工作原理 .
1st shortest path (K=1)
如果我们正在寻找开始和目的地之间的第一条最短路径(这里,在
D
和F
之间),我们可以运行Dijkstra的算法 . Yen算法在第一次迭代时的整个代码是:给定起始图,这给出了第一个最短路径(K = 1) .
2nd shortest path (K=2)
找到第二条最短路径的直觉是采用第一条最短路径但是“强制”Dijkstra算法沿着不同的,略微不太理想的路径 . Yen的算法沿着不同的路径“强制”Dijkstra算法的方式是删除作为第一条最短路径的一部分的边缘之一 .
但是我们删除哪条边以获得下一条最短路径?我们需要尝试逐个删除每个边缘,并查看哪个边缘移除为我们提供了下一个最短路径 .
首先,我们尝试删除边
D-E
(shortest_1
中的第一个边),然后通过运行Dijkstra(graph_1, D, F)
来完成最短路径 . 我们将节点D
已知的最短路径与D
(它只是节点D
本身)结合起来,使用从节点D
到F
的新最短路径 . 这为我们提供了另一条路径D->F
.然后我们尝试删除边
E-F
(shortest_1
中的第二个边),然后通过运行Dijkstra(graph_2, E, F)
来完成最短路径 . 我们将已知从节点D
到E
的最短路径与从节点E
到F
的新最短路径组合在一起 . 这为我们提供了另一种替代路径D->F
.因此,第二次迭代的过程如下所示:
最后,选择最短的替代新路径作为第二最短路径 .
3rd shortest path (K=3)
正如通过从第1个最短路径移除边缘找到第2个最短路径一样,通过从第2个最短路径移除边缘来找到第3个最短路径 .
然而,这次的新细微差别在于当我们删除边
D-A
(shortest_2
中的第一个边)时,我们还想删除边D-E
. 如果我们不这样做,只删除边D-A
,那么当我们在graph_3
上运行Dijkstra时,我们将再次找到第一条最短路径(D-E-F
),而不是第3条最短路径!但是,对于
graph_4
和graph_5
,我们不需要删除任何其他边,因为这些边在使用时不会给我们以前看到的最短路径 .因此,整个过程看起来类似于找到第二个最短路径,但是除了第二个最短路径之外,我们还希望去除在第一个最短路径中看到的一些边缘的细微差别 . 根据
shortest_1
和shortest_2
是否共享一条通向正被删除的边缘的子路径来做出决定 .注意当我们这次选择最短路径时,我们考虑迭代2中未使用的候选者(即
candidate_2
),并且实际上最终选择从graph_2
找到的最短路径 . 以同样的方式,在下一次迭代(K = 4)中,我们将发现第四条最短路径实际上是在迭代K = 3中找到的 . 正如您所看到的,此算法正在提前工作,因此在找到第K个最短路径时,它也在探索Kth最短路径之外的一些路径 . 因此,它不是Kth最短路径问题的最优算法 . Eppstein算法可以做得更好,但它更复杂 .通过使用几个嵌套循环可以推广上述方法 . Wikipedia page on Yen’s algorithm已经为更通用的实现提供了出色的伪代码,因此我将不再在此处编写它 . 请注意,维基百科代码使用列表
A
来保存每个最短路径,并使用列表B
来保存每个候选路径,并且候选最短路径在循环迭代中持续存在 .Remarks
由于使用了Dijkstra算法,Yen的算法不能具有包含循环的第K个最短路径 . 当使用未加权边缘时(如上例所示),这并不明显,但如果添加了权重,则可能发生这种情况 . 出于这个原因,Eppstein的算法效果也更好,因为它考虑了循环 . This other answer包含了对Eppstein算法的一个很好的解释 .
最佳(并且基本上是最优的)算法归因于Eppstein .
你_144139用于查找
K
最短路径的算法 . 然后,第_144141条最短路径将成为该组中的最后一条路径 .这是Yen算法的implementation .
这是描述它的original paper .
即使问题有一个有效的接受答案,这个答案通过提供样本工作代码来解决实现问题 . 在这里找到第k个最短路径的有效代码: