Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm Dijkstra和负边_Algorithm_Recursion_Dijkstra - Fatal编程技术网

Algorithm Dijkstra和负边

Algorithm Dijkstra和负边,algorithm,recursion,dijkstra,Algorithm,Recursion,Dijkstra,我很难理解为什么Dijkstra的算法不适用于具有负边的无环有向图。据我所知,Dijkstra对图进行宽度优先遍历,在适当的时候放松。例如,考虑图: S->A (3) S->B (4) B->A (-2) 其中S是源节点。这就是我想象的工作方式: 1标记A,距离为3。标记距离为4的B 2在A上递归。由于A不指向任何节点,因此不执行任何操作 3在B上递归。由于B指向A,请检查B的距离+B->A是否小于A的当前距离。2A。因为不再有来自B的传出边,所以我们完成了 编辑2: 关于D

我很难理解为什么Dijkstra的算法不适用于具有负边的无环有向图。据我所知,Dijkstra对图进行宽度优先遍历,在适当的时候放松。例如,考虑图:

S->A (3)
S->B (4)
B->A (-2)
其中S是源节点。这就是我想象的工作方式:

1标记A,距离为3。标记距离为4的B

2在A上递归。由于A不指向任何节点,因此不执行任何操作

3在B上递归。由于B指向A,请检查B的距离+B->A是否小于A的当前距离。2<3,因此用距离2标记A


但显然这不是它的工作原理,因为我用的书给出了这个图表来说明为什么负片不起作用。我听不懂这本书的解释。Dijkstra如何处理这张图,为什么他们不使用我想象的方法?

问题是,一旦处理一个节点,之后就无法更新其距离,因为这将需要递归更新,并将放弃整个读取过程:违背算法的假设,即节点是在与源的距离单调增加的情况下处理的;请参阅该算法的正确性证明,以了解需要该算法的地方。因此,一旦处理了一个节点,以后就不能更改其距离,这意味着不能有负边,因为它们可能会缩短到先前处理的节点的距离。假设距离单调增加,这就是为什么处理完节点后将其标记为黑色,然后忽略黑色节点的原因。因此,即使在该图中,A的距离是2到S,Dijkstra的算法也会给你一个3的距离,因为它忽略了在A被处理后通向A的任何边

编辑:以下是Dijkstra的算法的作用:

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

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

3把B带出队列。B指向A,但A标记为已处理;忽略边B->A。因为不再有来自B的传出边,所以我们完成了

编辑2:
关于DAG,您根本不需要Dijkstra算法。DAG总是有一个拓扑顺序,可以用O | V |+| E |计算,并按照拓扑顺序处理顶点,使用dw=min{dw;dv+cv,w}作为更新距离的规则,其中dv是顶点V到源的距离,而cv,w是边V的长度,w将同样在O | V |+| E |中给出正确的距离。总共有两个步骤,每个步骤都需要O | V |+| E |,因此这就是计算具有任意边长度的DAG中单源最短路径的总复杂性。

问题是,一旦处理节点,之后就无法更新其距离,因为这将需要递归更新,并将放弃整个读取过程:违背算法的假设,即节点是在与源的距离单调增加的情况下处理的;请参阅该算法的正确性证明,以了解需要该算法的地方。因此,一旦处理了一个节点,以后就不能更改其距离,这意味着不能有负边,因为它们可能会缩短到先前处理的节点的距离。假设距离单调增加,这就是为什么处理完节点后将其标记为黑色,然后忽略黑色节点的原因。因此,即使在该图中,A的距离是2到S,Dijkstra的算法也会给你一个3的距离,因为它忽略了在A被处理后通向A的任何边

编辑:以下是Dijkstra的算法的作用:

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

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

3把B带出队列。B指向A,但A标记为已处理;忽略边B->A。因为不再有来自B的传出边,所以我们完成了

编辑2: 关于DAG,您根本不需要Dijkstra算法。DAG总是有一个拓扑顺序,可以用O | V |+| E |计算,并按照拓扑顺序处理顶点,使用dw=min{dw;dv+cv,w}作为更新距离的规则,其中dv是顶点V到源的距离,而cv,w是边V的长度,w将同样在O | V |+| E |中给出正确的距离。总共有两个步骤,每个步骤都需要O | V |+| E |,因此这就是计算具有任意边长度的DAG中单源最短路径的总复杂性