Dijkstra和Negative Edges

时间:2013-03-27 22:35:13

标签: algorithm recursion dijkstra

我无法理解为什么Dijkstra的算法不适用于具有负边缘的非循环有向图。据我了解,Dijkstra对图表进行了广度优先遍历,适当时放松。例如,考虑图表:

S->A (3)
S->B (4)
B->A (-2)

其中S是源节点。这就是我想象的工作方式:

1)标记A,距离为3.标记B,距离为4.

2)递归A.由于A指向无节点,不执行任何操作。

3)递归B.由于B指向A,检查B的距离+ B-> A是否小于当前距离A. 2< 3,所以用距离2标记A.

然而显然这不是它的工作方式,因为我使用的书给出了这个图表,以说明为什么否定不起作用。我不能按照这本书的解释。 Dijkstra如何处理这个图表,为什么他们不使用我想象的方法?

1 个答案:

答案 0 :(得分:4)

问题是,一旦你处理了一个节点,你就不能事后更新它的距离,因为这需要递归更新并且会抛弃整个事物(读取:违背算法的假设,单调处理节点)增加与源的距离;查看算法的正确性证明,以查看所需的位置)。因此,一旦处理完A,您就无法在以后更改其距离,这意味着您不能有负边缘,因为它们可能会使您与先前处理的节点的距离更短。单调增加距离的假设是为什么在处理后将节点标记为黑色,然后忽略黑色节点。因此,即使在该图A中距离为2到S,Dijkstra的算法也会给你3个距离,因为它忽略了A处理后通向A的任何边缘。

编辑:这是Dijkstra算法的作用:

1)标记距离为3的A,将其放入等待处理的节点队列中;将B标记为距离4,将其放入队列中。

2)将A从队列中取出,因为它在前面。由于A指向无节点,不更新任何距离,因此不要向队列添加任何内容。将A标记为已处理。

3)将B从队列中取出。 B指向A,但A标记为已处理;忽略边B-> A。由于B没有更多的传出边缘,我们已经完成了。

编辑2: 关于DAG,您根本不需要Dijkstra的算法。 DAG始终具有拓扑排序,可以在O(| V | + | E |)中计算,并使用d(w) = min {d(w); d(v) + c(v, w)}作为更新d(v)距离的规则,以拓扑顺序处理顶点是顶点v与源的距离,而c(v,w)是边(v,w)的长度,它将为您提供正确的距离,同样在O(| V | + | E |)中。总共有两个步骤,每个步骤都需要O(| V | + | E |),因此这是计算具有任意边长的DAG中单源最短路径的总复杂度。