有人可以告诉我为什么这个dijkstra算法的实现不适用于负权重?

时间:2016-01-12 20:27:04

标签: java algorithm dijkstra

我已经查看了dijkstra算法found here的实现,但它似乎适用于负权重。

具体来说,relax方法更新优先级队列中的顶点距离,或者如果它最初不在队列中,则将其重新插入。

由于没有任何检查以确保我们不会重新插入已知的顶点,因此这种实现更像是一个Bellman-ford算法,我们不断插入顶点进行访问并放松直到减少距离的边缘?

例如:

在下面的图像上以A作为来源运行时,我们首先确定以下距离:

C = 0
B = 1
D = 99

然后在我们的队列删除后,我们留下(D,99),这使我们访问顶点D并放松它。当放松顶点D时,我们发现(D到B = -300),这使得到B的距离为-201。现在使用"放松"上面的方法,我们重新插入(B,-201)队列。现在我们取队列的最小值,即我们刚插入的(B,-201)。由此,我们放松B,我们可以到C的距离为-200。

enter image description here

我知道任何负面循环都会使程序无法终止,但是如果给出一个没有负循环的图形怎么办? 希望我在这里不会错过任何微不足道的事情。谢谢你的帮助!

2 个答案:

答案 0 :(得分:0)

因为如果你输入负重,它将malloc()

答案 1 :(得分:0)

Dijkstra基于这样的事实,即一旦访问节点并且其所有边缘都“被使用”,它就不再被访问,因此复杂性很低(不需要“重新平衡整个图形”。)< / p>

这两者都是基于非负边缘,因为如果存在负面边缘,则必须“重新平衡”它们,复杂性会上升很多。正如你所提到的,负循环的循环根本不会结束。

作者抛出异常的原因是因为他不想处理“无效”图形,特别是无休止的循环。

PS:您的特定图形实际上应该可以由Dijkstra解决,但想象这个图形具有负边缘且没有周期:

A ->(1) B ->(1) -> C
|      (-300)
v       ^
(5)     |
D ->(1) E 

你真的解决了

B=1
C=2

在此之后你关闭A,B和C并且不想再次输入它们。但在此之后,您发现A-> D-> E-> B是-294,然后您重新输入所有其他值。

想象一下为什么这么糟糕,我给你另一个例子

    A ->(1) B ->(1) -> C -> SUPERGRAPH
    |    (-999999)
    v       ^
  (99999)   |
    D ->(1) E 

所以现在A-&gt; D是非常高的值而C指向一些SUPERGRAPH但是从A开始总长度不超过99999。

会发生什么?即使这有效并且没有其他周期,你也可以从A中解决整个超图,但在此之后,你会发现实际上A-> B更短,你必须再次解决整个SUPERGRAPH。如果你有更多这样的情况,对于每一个,你必须再次运行Dijkstra alghoritm。