【问题标题】:Dijkstra Algorithm = SSSPDijkstra 算法 = SSSP
【发布时间】:2016-08-06 06:24:42
【问题描述】:

我了解到,dijkstra 不能使用负边权重。为此,我们必须使用 bellman ford。

Bellman fords 可以很好地处理负边权重和负循环,否则无法从源访问,它将返回消息“存在负循环”。

但是,即使存在负边权重,上面显示的这张图也适用于 dijkstra。那么,如何知道何时使用带负边权重的 dijkstra 呢??

认为,dijkstra 可以或不能使用负权重边缘。 如果存在负循环,则它将不起作用。但如果不存在,它可以或不能工作。

我说的对吗??请指导我这个??

【问题讨论】:

    标签: algorithm dijkstra


    【解决方案1】:

    Dijkstra 算法不适用于负边权重。这是因为一旦它将一个节点标记为“已访问”,它就会假定已经找到了到它的最短路径,并且不能改变,在带有负边(并且没有负循环)的图中很容易违反不变量:

           A
          / \
        7/   \2
        /     \
       B------>C
          -6
    

    使用 Dijkstra 算法从 A 开始寻找最短路径会为 C 产生错误的成本,2

    您发布的图表也不起作用:考虑从dh 的最短路径。该图上的 Dijkstra 将为路径 (d->g->h) 生成 4,而成本为 0 的路径更便宜:d->a->b->c->h

    【讨论】:

    • 但是,在我的图表中查看从 A 到 E 的距离。最小路径是-2,在遍历完整图之后,我没有发现到 E 的任何距离小于 -2,这意味着它在这里没有违反。在你的例子中,它肯定是违反的。
    • 仅仅因为一个结果是偶然正确的,并不能使所有其他结果也正确。我想我已经证明,如果您的图表至少包含一条负权边,您就不能依靠 Dijkstra 的算法来找到最短路径。
    • 你是对的,但如果我只想从 A 找到最短路径,那么它会起作用吗?我了解 D ,它不会起作用。
    • 一般情况下不起作用。当我向您展示它可能是错误的时,您将如何验证其对 A 的输出是否正确?使用正确的算法。
    • 是的,我明白了。谢谢 。警惕 dijkstra 的负边权重。
    【解决方案2】:

    Dijkstra 不能使用负权重边缘。 有一个名为 Johnson 的算法,它对图中的所有边“重新加权”,最后使所有边为正。但该算法称为贝尔曼福特算法,其时间复杂度为 O(V2logV + VE)。 所以 Dijkstra + Johnson 的时间复杂度不好。但是如果可以处理图,说不定可以提前使用算法。 PS:对不起我的英语不好。

    【讨论】:

      【解决方案3】:

      检查以下代码

          import networkx as nx
          g = nx.Graph()
          g.add_edge(1, 2, weigbt=-10)
          g.add_edge(2, 3, weight = -5)
          g.add_edge(1, 3, weight =-6)
          print(nx.single_source_dijkstra(g, 1, 3))
      

      无论您的所有边是正面还是负面,Dijkstra SSSP 都会给您相同的答案。 但是,这并不意味着对于任何具有负边的图,Dijkstra 最短路径可能会在负边的情况下给出正确的答案,但这并不意味着它会给出正确的答案。

      【讨论】:

        【解决方案4】:

        你是对的,Dijkstra 将适用于负权重。但是,如果任何循环中的权重总和为负数,它将不起作用。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-03-13
          • 2011-06-27
          • 2021-07-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多