dijkstra算法为什么不能计算负权重?

  这几天在看迪杰斯特拉算法(dijkstra算法)的时候,了解到这个算法不能够计算负权重,这让我很纳闷???为什么呢???下面我按照我理解的解释一番,若有错误希望阅读者能够评论指出,不胜感激。
dijkstra算法为什么不能计算负权重?_第1张图片
我们看上图,求A到其他节点的最短路径:
  首先得出A -> B = 1,A -> C = 0,A -> D = 99,然后将A被标记访问过。
接着找B到其他节点的距离,看看能不能更新上述节点间距离或者找到其他新节点。找到一个B -> C = 1,A -> B + B -> C = 2 > A -> C = 0,所以不予更新A -> C的节点距离,此时将B被标记访问过。
  再接着找C到其他节点的距离,发现C那个节点也到不了,也没有发现新节点,此时将C被标记访问过。
  再接着重点就来了,D -> B = -300,保证了A -> D + D -> B = -201 < A -> B = 1,则更新A -> B = -201,此时将D被标记访问过。
  但是,我们明显可以看出,A -> D + D -> B + B -> C = -200 < A -> C = 0,也就是说应该更新A -> C = -200,但是再进行D的操作前,A,B,C三个节点已经被标记访问过。此时无法访问了啊。
  这就是它无法计算负权重的原因,但并不是这个算法在所有包含负权重的图都无法正确计算。然后既然dijkstra算法计算负权重是有问题的,有什么算法来解决嘛?怎么解决的呢?

首先有一个解决算法——Bellman-ford算法,我们可以看下面这篇博客了解它的处理步骤。
Bellman-ford算法详解——负权环分析
  按照Bellman-ford算法的步骤,我们先初始化节点A到本身和其他节点的距离为dis[0, inf,inf,inf],然后再保存所有边的权值以及边的两个节点(A -> B = 1,A -> C = 0,A -> D = 99,D -> B = -300,B -> C = 1),接着双重循环(一会解释为什么要双循环)。
  1.第一条边A -> B = 1,判断dis[B] > dis[A] + A -> B => inf > 0 + 1 => true , 则更新dis[0, 1,inf,inf];
  2.第二条边A -> C = 0,判断dis[C] > dis[A] + A -> C => inf > 0 + 0 => true ,则更新dis[0, 1,0,inf];
  3.第三条边A -> D = 99,判断dis[D] > dis[A] + A -> D => inf > 0 + 99 => true ,则更新dis[0, 1,0,99];
  4.第四条边D -> B = -300,判断dis[B] > dis[D] + D -> B => 1 > 99 + (-300) => true ,则更新dis[0, -201,0,99];
  5.第四条边B -> C = -300,判断dis[C] > dis[B] + B -> C => 0 > -201 + 1 => true ,则更新dis[0, -201,-200,99];
  此时按照人工判断已经是最短路径了,不需要最外层的循环了,但是为什么还要最外层循环呢?最里层的循环我们已经知道了,是遍历边!!!,最外层的循环其实也是遍历边,为什么?你想一想经过最里层的遍历边后,边的权值路径是不是都更新了?万一其他边还可以基于上次更新的边再次更新呢?最外层的循环就是为了处理这个情况。
  外层循环只节点数-1次,因为最短路径就算包括所有顶点(这些顶点肯定是不重复的),那么边最多也就有节点数–1个。而外层循环在算法中的含义就是,每执行一次外层循环,那么便最短路径的边的个数加1,所以外层循环只节点数-1次。
  内层循环待表的是总边数。
这种算法有什么缺点或者优化吗?
  缺点:不可以出现负权环。
  这是为什么呢?举个例子
dijkstra算法为什么不能计算负权重?_第2张图片
  1.第一次遍历后,点C的值变为5,点B的值变为8,这时,注意权重为-10的边,这条边的存在,导致点A的值变为-2。(8+-10=-2)。
  2.第二次遍历后,点C的值变为3,点B变为6,点A变为-4。
  …
  正是因为有一条负边在回路中,导致每次遍历后,各个点的值不断变小。而且这是无限循环的。
  优化:正如我们第一个例子,在循环一次就已经确定了最短路径,但是按照原算法还要继续进行循环下去,这是无用功呢,于是可以在循环中设置判定,在某次循环不再进行松弛时,直接退出循环,进行负权环判定。
如果文中我的理解有偏差或者错误,请阅读者评论指出,不胜感激。

你可能感兴趣的:(算法练习,dijkstra,负权重,Bellman-Ford,SPFA)