使用Dijkstraalgorithm的负权重

我想了解为什么Dijkstraalgorithm不能用负权重。 阅读最短path示例,我试图找出以下情况:

2 A-------B \ / 3 \ / -2 \ / C 

从网站:

如果我们从A开始,那么Dijkstra的algorithm将select最小化d(A,A)+长度(边)的边(A,x),即(A,B)。 然后设d(A,B)= 2并select另一个边(y,C),使d(A,y)+ d(y,C)最小。 唯一的select是(A,C),它设置d(A,C)= 3。 但它从来没有find从A到B的最短path,通过C,总长度为1。

我不明白为什么使用下面的Dijkstra的实现,d [B]不会更新到1 (当algorithm到达顶点C时,它将在B上运行放松,看到d [B]等于2 ,并且因此将其值更新为1 )。

 Dijkstra(G, w, s) { Initialize-Single-Source(G, s) S ← Ø Q ← V[G]//priority queue by d[v] while Q ≠ Ø do u ← Extract-Min(Q) S ← SU {u} for each vertex v in Adj[u] do Relax(u, v) } Initialize-Single-Source(G, s) { for each vertex v  V(G) d[v] ← ∞ π[v] ← NIL d[s] ← 0 } Relax(u, v) { //update only if we found a strictly shortest path if d[v] > d[u] + w(u,v) d[v] ← d[u] + w(u,v) π[v] ← u Update(Q, v) } 

谢谢,

梅厄

你所build议的algorithm确实会在这个图中find最短path,但并不是所有的图都是一般的。 例如,考虑这个图表:

图的图

假设边缘是从左到右,如你的例子,

你的algorithm将如下工作:

  1. 首先,将d(A)设置zero ,其他距离设置为infinity
  2. 然后展开节点A ,将d(B)设置为1 ,将d(C)设置zero ,将d(D)99
  3. 接下来,你展开C ,没有净变化。
  4. 然后,你扩大了B ,这是没有效果的。
  5. 最后,展开D ,它将d(B)更改为-201

注意,尽pipeC的最短path长度为-200 ,但d(C)仍然为0 因此,在某些情况下,您的algorithm无法准确计算距离。 而且,即使你要存储返回指针,说明如何从每个节点到开始节点A ,你也会结束从CA的错误path。

请注意,如果图表没有负循环,即加权总和小于零的循环,那么Dijkstra即使对于负权重也是有效的。

当然,有人可能会问,为什么在templatetypedef的例子中,即使没有负循环,Dijkstra也会失败,事实上甚至不是循环。 这是因为他正在使用另一个停止标准,一旦到达目标节点(或者所有节点已经被解决一次,他没有确切地指定)就保存该algorithm。 在没有负重的图表中,这可以正常工作。

如果使用替代停止标准,当优先级队列(堆)运行空闲时停止algorithm(这个停止标准也用于问题中),那么dijkstra即使对于具有负权重的图也能find正确的距离负循环。

然而,在这种情况下,没有负循环的图的dijkstra的渐近时间范围是丢失的。 这是因为当由于负权重而发现更好的距离时,先前定居的节点可以被重新插入到堆中。 这个属性被称为标签更正。

你没有在algorithm的任何地方使用S(除了修改它)。 dijkstra的概念曾经是一个顶点在S上,它不会再被修改。 在这种情况下,一旦B在S内部,你将不会再通过C.

这个事实确保了O(E + VlogV)的复杂性[否则,你将会重复多次一次的边,并且多于一次的顶点]

换句话说,您发布的algorithm可能不在O(E + VlogV)中,正如dijkstra的algorithm所承诺的那样。

由于Dijkstra是一个贪婪的方法,一旦一个顶点被标记为这个循环的访问,即使有另外一条path以较低的成本到达,它也不会再被重新评估。 而这样的问题只有在图中存在负边时才会发生。


一个贪婪的algorithm ,顾名思义, 总是让这个select似乎是当时最好的。 假设你有一个目标函数需要在给定的点上进行优化(最大化或最小化)。 贪婪algorithm在每一步都会进行贪婪的select,以确保目标函数得到优化。 贪婪algorithm只有一个镜头来计算最佳解决scheme,以便它永远不会倒退,并决定。

考虑一下如果你在B和C之间来回发生什么事,那么瞧吧

(只有在图表没有被引导时才相关)

编辑:我认为这个问题与AC *的path只有在负权重边缘存在的情况下才会比AB好,因此,在AC之后去哪里并不重要,一旦你select去AC之后到达B,那么就不可能find比AB更好的path。

“2)我们可以使用Dijksra的algorithm为具有负权的图的最短path – 一个想法可以是,计算最小权重值,向所有权重添加正值(等于最小权重值的绝对值)并运行Dijksraalgorithm对于修改后的图,这个algorithm会起作用吗?

除非所有最短path具有相同的长度,否则这绝对不起作用。 例如给定一个长度为两条边的最短path,并且在给每条边添加绝对值之后,总path成本增加2 * | max negative weight |。 另一方面,另一条长度为三条边的path,所以path成本增加3 * |最大负重|。 因此,所有不同的path增加了不同的数量。