Dijkstra是DAG中最长的路径

时间:2011-11-06 13:10:34

标签: dijkstra longest-path

我试图找出是否有可能使用Dijkstra算法找到有向非循环路径中的最长路径。我知道由于负成本周期,在一般图表中找不到Dijkstra的最长路径是不可能的。但我认为它应该在DAG中起作用。通过谷歌,我发现了很多相互矛盾的消息来源。有人说它在dag中工作,有些人说它不起作用,但我没有找到证据或反例。有人能指出我的证据或反例吗?

6 个答案:

答案 0 :(得分:6)

我想到了这个问题,我认为一般来说这是不可能的。我想,存在非循环是不够的。

例如:

我们想在这个dag中从a到c。

a - > b - > c
|           /\
v           |
d - - - - - 

d-c长度为4

a-d的长度为1

所有其他人的长度都是2

如果你只用最大函数替换min函数,算法将导致a-b-c,但最长的路径是a-d-c。

我发现了两个特殊情况,您可以使用Dijkstra计算最长路径:

  1. 图表不仅指向非循环,而且如果您删除指示也是非循环的。换句话说:它是一棵树。因为在树中,最长的路径也是最短的路径。
  2. 图表只有负权重。然后你可以使用max而不是min来找到最长的路径。但这只适用于权重确实为负的情况。如果你只是反转正重量它将无法正常工作。

答案 1 :(得分:4)

对于任何图表,DAG与否,最长距离问题没有最佳子结构。然而,图G上的任何最长距离问题等同于变换图G中的最短距离问题G = = G,即每个边权重的符号被反转。

如果转换后的图形G'预计具有负边缘和周期,然后使用Bellman-Ford算法寻找最短距离。但是,如果G保证只有非负权重(即G'是非正权重),那么Dijkstra算法可能是比Bellman-Ford更好的选择。 (参见' Evgeny Kluev' graph - Dijkstra for The Single-Source Longest Path的回复)如果G是DAG,那么G'也将成为DAG。对于DAG,我们有更好的查找最短距离的算法,应该选择Dijkstra或Bellman-Ford。

<强>要点:
最长的路径问题没有最优的子结构,因此将Dijkstra算法中的最小权重函数修改为单独的最大权重函数不会对图表起作用,无论是否为DAG。我们宁愿转换G,而不是修改任何最短路径算法(以微不足道的方式),并且看看哪个最短路径算法在转换后的G上效果最好。

注意

     A-------B
     |       |              assume: edges A-B, B-C, C-A of same weight
     |       |
     +-------C

我们看到MAX_DIS(A,B)= A-> C-> B
对于&#34; MAX_DIS&#34;在上述情况下,为最佳结构,关系

    MAX_DIS(A,B) = MAX_DIS(A,C) + MAX_DIS(C,B) should be satisfied.

但它不是我们所看到的,MAX_DIS(A,C​​)= A-> B-> C和MAX_DIS(C,B)= C-> A-> B因此它提供了一个例子最长距离问题可能没有最佳的子结构。

答案 2 :(得分:1)

有三种可能的方式来应用Dijkstra,其中没有一种可以使用:
1.直接使用“最大”操作而不是“最小”操作 2.将所有正权重转换为负数。然后找到最短的路径 3.给出一个非常大的正数M.如果边的权重是w,那么现在用M-w代替w。然后找到最短的路径。

对于DAG,关键路径方法将起作用:
1:找到拓扑排序。
2:找到关键路径 参见[Horowitz 1995] E. Howowitz,S。Sahni和D. Metha,C ++数据结构基础,计算机科学出版社,纽约,1995

答案 3 :(得分:0)

唯一的要求是不要有负循环。如果您没有周期,则可以通过将负权重中的最高绝对值添加到所有权重来重新映射负数。这样你就会失去负面的重量,因为所有的重量将等于或大于零。总而言之,唯一要担心的是没有负面循环。

答案 4 :(得分:0)

我建议您修改Dijkstra算法以获取边权重的倒置值。由于图形是非循环的,因此算法不会进入无限循环,使用负权重来保持优化。更重要的是,现在权重变为负数,但同样没有周期。即使图形无向,这也会起作用,前提是您不允许重新插入受访节点(即,停止两个节点之间的无限跳跃,因为添加负值总是会更好)。

答案 5 :(得分:0)

信誉不足,无法对@punkyduck's answer进行评论,但是我想提到在DAG中用min替换max

a ——2——→ b ——2——→ c
│                 ↑
│                 │
1                 4
│                 │
└——————→ d ———————┘

实际上是可行的,就像算法会

  • 首先检查aab=2, ad=1l(b)=(ab,2), l(d)=(ad,1)
  • 然后检查b,因为我们使用maxabc=2l(c)=(abc,2)
  • 然后从c开始检查abc>ad什么都没发生
  • 最后检查dadc=5⇨更新l(c)=(adc,5)

因此,在最后一步,找到了正确的最长路径adc。只是指出错误。