Dijkstra的负权重算法

时间:2011-05-10 21:13:15

标签: dijkstra

我们可以使用具有负权重的Dijkstra算法吗?

停止!在你认为“大笑之后,你可以无休止地在两点之间跳跃并获得一条无限廉价的道路”之前,我更多地考虑单向路径。

申请将是一个山区地形,上面有点。显然,从高到低不会消耗能量,事实上,它会产生能量(因此负路径重量)!但是再往后就不会这样,除非你是查克诺里斯。

我在考虑增加所有点的权重,直到它们是非负数,但我不确定这是否会起作用。

7 个答案:

答案 0 :(得分:58)

只要图形不包含负循环(边缘权重为负和的有向循环),它将在任意两点之间具有最短路径,但Dijkstra算法不是为了找到它们而设计的。用于在具有负边缘权重的有向图中找到单源最短路径的最着名算法是Bellman-Ford algorithm。然而,这需要付出代价:Bellman-Ford需要O(| V |·| E |)时间,而Dijkstra's需要O(| E | + | V | log | V |)时间,这是渐近的两个稀疏图(其中E是O(| V |))和密集图(其中E是O(| V | ^ 2))的速度更快。

在你的山地地形的例子中(必然是directed graph,因为上坡和下坡有不同的权重),不存在负循环的可能性,因为这意味着留下一个点然后返回到它具有净能量增益 - 可用于创建perpetual motion machine

将所有权重增加一个常数值,使它们为非负值将不起作用。要看到这一点,请考虑从A到B有两条路径的图形,一条遍历长度为2的单条边,另一条遍历长度为1,1和-2的遍历边。第二条路径较短,但如果将所有边缘权重增加2,则第一条路径现在的长度为4,第二条路径的长度为6,从而反转最短路径。只有当两点之间的所有可能路径使用相同数量的边时,此策略才有效。

答案 1 :(得分:3)

如果您阅读最优性证明,则所做的假设之一是所有权重都是非负的。所以,没有。正如Bart推荐的那样,如果你的图表中没有负循环,请使用Bellman-Ford。

您必须明白,负边缘不仅仅是负数 - 它意味着路径成本中的减少。如果在路径中添加负边缘,则减少路径的成本 - 如果增加权重以使此边缘现在为非负数,则它没有减少属性再这样,这是一个不同的图。

我鼓励您阅读最优性证明 - 您将看到,在现有路径中添加边缘只能增加(或不影响)路径成本的假设至关重要。

答案 2 :(得分:1)

您可以在负加权图上使用Dijkstra,但首先必须为每个顶点找到适当的偏移量。这基本上是约翰逊的算法所做的。但是,由于约翰逊使用贝尔曼 - 福特来寻找重量偏移量,这将是一种过度杀伤力。 Johnson's设计用于顶点对之间的所有最短路径。

http://en.wikipedia.org/wiki/Johnson%27s_algorithm

答案 3 :(得分:1)

实际上有一种算法在负路径环境中使用Dijkstra算法;它通过删除所有负边缘并首先重新平衡图表来实现。该算法称为“约翰逊算法”。

它的工作方式是添加一个新节点(比方说Q),它有0成本遍历到图中的每个其他节点。然后它从点Q在图表上运行Bellman-Ford,得到每个节点相对于Q的成本,我们称之为q [x],它将为0或负数(因为它使用了一个负路径)。

E.g。 a - > -3 - > b,因此如果我们向所有这些节点添加一个成本为0的节点Q,那么q [a] = 0,q [b] = -3。

然后我们使用公式重新平衡边缘:weight + q [source] - q [destination],所以a-> b的新权重是-3 + 0 - (-3)= 0.我们做这对于图中的所有其他边缘,然后删除Q及其外出边缘瞧!我们现在有一个没有负边的重新平衡图,我们可以在其上运行dijkstra!

运行时间为O(nm)[bellman-ford] + nx O(m log n)[n Dijkstra] + O(n ^ 2)[权重计算] = O(nm log n)时间

更多信息:http://joonki-jeong.blogspot.co.uk/2013/01/johnsons-algorithm.html

答案 4 :(得分:0)

实际上我觉得修改边缘权重会起作用。没有偏移但有一个因素。假设您不是测量距离,而是测量从A点到B点所需的时间。

重量=时间=距离/速度

如果您的任务是真正的山脉和汽车/自行车,您甚至可以根据坡度调整速度来使用物理速度。

答案 5 :(得分:0)

是的,你可以在最后增加一步,即

            If v ∈ Q, Then Decrease-Key(Q, v, v.d)
            Else Insert(Q, v) and S = S \ {v}.

答案 6 :(得分:-2)

表达式树是一个二叉树,其中所有叶子都是操作数(常量或变量),非叶子节点是二元运算符(+-/*^)。实现此树以使用树的基本方法对多项式进行建模,包括以下内容:

  1. 计算多项式的一阶导数的函数。
  2. 评估给定x值的多项式。
  3.   

    [20]对导数使用以下规则:导数(常数)= 0导数(x)= 1导数(P(x)+ Q(y))=导数(P(x))+导数(Q) (y))导数(P(x) - Q(y))=导数(P(x)) - 导数(Q(y))导数(P(x)* Q(y))= P(x)*导数(Q(y))+ Q(x)*导数(P(x))导数(P(x)/ Q(y))= P(x)*导数(Q(y)) - Q(x) *导数(P(x))导数(P(x)^ Q(y))= Q(y)*(P(x)^(Q(y)-1))*导数(Q(y))< / p>