关于普通dij算法为什么不能解决负权边的分析

我们首先来分析下含负权边的无向图:
这里写图片描述
1.先看图
我们求A点到C点的最短距离,很明显答案为1.
2.我们用dij来跑下,看过程:

  • 先把A点标记哈,不需要访问本身
  • 首先找到距A最近的且直接相连的点(也就是两点间没有中转点)C,把C标记哈
  • 找出C点的出点A,,B,A被标记了不管,此时A到B的距离为3,大于A到C的距离加上C到B的距离0,所以更新A到B的距离为0
  • 更新后A到C的距离仍然为2,A到B的距离为0,A,C都被标记,只有B未被标记,进行下一步
  • 找到距A最近的且未被标记的点B,标记B
  • 找出B的出点A,C,然而A,C两点都被标记,不能松弛
  • 好,程序结束,结果为A到C的距离为2而不是1,说明普通dij并不能处理带负权边的无向图

3.看完了dij过程可能仍有人不是很明白为什么,没关系,待会儿会详细解释,现在我们看下带负权边的有向图:
这里写图片描述
4.如图,我们还是求A到C的最短距离,很明显,答案还是15.我们还是用dij来跑下:

  • 先把A点标记哈,不需要访问本身
  • 首先找到距A最近的且直接相连的点(也就是两点间没有中转点)C,把C标记哈
  • 找出C点的出点,哦豁,莫得,不方,莫得就不管,走下一步
  • 找到距A最近的且未被标记的点B,标记B
  • 找出B的出点C,好,松弛,等等!!!松弛个锤子,C是标记了的,按照dij远的点是不能松弛近的点的,所以不能松弛。
  • 好,程序结束,结果为A到C的距离为2,跟答案不同。说明也不能用dij来处理带负权边的有向图。

PS(有的人在倒数第二步没有判断点是否标记,导致求出来的结果是1,然而这时错误的,下面我将说明)
6.我们来看看原因:
我们先来看看dij的由来,dij求最短路的算法是由贪心得来的,也就是说长路径的松弛正确的前提是用来松弛它的短路径是最短的,也就是说在之后是不会变的,这在非负权值的情况下是对的,然而遇到负权值便错了,因为当加入了负权值边后便可能使之前的短边变得更短,就如图中一样,我们先访问了C点,则AC的距离在之后的距离应该是不变的,这在都是非负权值时是正确的,因为每条边都是非负的,当通过其他点来中转时,所经过的路径和必然不小于AC的距离,然而加入了负权边后,使得AC的距离变得比初始更小,这便使得前提错误,前提都错了,dij算法便不成立,结果便错误,这也是为什么有那么多人糊涂的原因,也是我专门举这个例子的原因

*

你可能感兴趣的:(算法解惑)