Dijkstra's 最短路径算法能不能解这个含有负权重的问题

Q. Does Dijkstra's algorithm work with negative weights?

A. Yes and no. There are two shortest paths algorithms known as Dijkstra's algorithm, depending on whether a vertex can be enqueued on the priority queue more than once. When the weights are nonnegative, the two versions coincide (as no vertex will be enqueued more than once). The version implemented in DijkstraSP.java (which allows a vertex to be enqueued more than once) is correct in the presence of negative edge weights (but no negative cycles) but its running time is exponential in the worst case. (We note that DijkstraSP.java throws an exception if the edge-weighted digraph has an edge with a negative weight, so that a programmer is not surprised by this exponential behavior.) If we modify DijkstraSP.java so that a vertex cannot be enqueued more than once (e.g., using a marked[] array to mark those vertices that have been relaxed), then the algorithm is guaranteed to run in E log V time but it may yield incorrect results when there are edges with negative weights.

上述代码来自https://algs4.cs.princeton.edu/code/edu/princeton/cs/algs4/DijkstraSP.java.html;

以下摘自知乎:

对于有负权边但无负权回路的图:


1、如果是标准的O(V^2)的Dijkstra,那是算不出的(除非碰巧算对);

2、如果是优先队列优化(或者说堆优化)的版本,也不行(除非碰巧算对);

3、如果是优先队列优化+允许重入队,那么可以(是真的可以计算出来,不是碰巧)。此算法被国内的ACMer称为spfa,但这实际上已经是priority queue-based Bellman-Ford了,是Bellman-Ford算法的变种。(国外好像习惯把这个算法仍旧叫做堆优化的Dijkstra,看作Dijkstra的变种,可能是习惯不一样吧。不过此时已经说不清这到底是Dijkstra还是Bellman-Ford算法了……)


允许重入队的意思是,对于已经出队的节点,如果它的距离标号还能被更新,那么还要进行更新,再次入队。第三种算法和第二种算法的根本区别是:已经出队的节点并非已经确定最短路径的节点,它的距离标号之后还可以进行更新。第三种算法的时间复杂度不好分析,算法的运行时间依赖于输入数据的分布。在非负权图的情况下,此算法与第二种算法行为完全相同,时间复杂度为O((V+E)*lg V);而对于有负权边但无负权回路的图,算法的最坏运行时间是顶点数目的指数。(具体参见 courses.engr.illinois.edu)不过实际运行起来往往比较快,远好于理论上界,在有负权边而无负权回路的图上,如果运气不是特别差的话,行为通常像是O(E)的。


作者:知乎用户
链接:https://www.zhihu.com/question/21620069/answer/24518138
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值