关于单源最短路算法 dijkstra不能用来算含负权边的原因
dijkstra:贪心算法,每次选取未访问结点到已访问集合的d最小值,
该节点x加入已访问集合,并用该点x更新其临边到已访问集合的距离d
具体为:
1.将图上的初始点看作一个集合S,其它点看作另一个集合
2.根据初始点,求出其它点到初始点的距离d[i] (若相邻,
则d[i]为边权值;若不相邻,则d[i]为无限大)
3.选取最小的d[i](记为d[x]),并将此d[i]边对应的点
(记为x)加入集合S
4.再根据x,更新跟 x 相邻点 y 的d[y]值:d[y] = min{
d[y], d[x] + 边权值w[x][y] },因为可能把距离调小,所以这个更新操作叫做松弛操作。
5.重复3,4两步,直到目标点也加入了集合,此时目标点所
对应的d[i]即为最短路径长度。
注意:该种做法每次从未被访问的集合种选出点x后,只会更新直接与x相邻的点的距离d,
更新后,再从未被访问的集合中选点,重复操作
1.如果是正权图,集合内的点到初始点的最短距离已经确认了,
把没在集合内的点加入路径只可能会增加无用的边,也就增加了路径长度;
所以只根据集合内点的邻边来更新,就能得到当前的最小d[x]了。
2.但如果是负权图,注意上句话中的文字 “把没在集合内的点加入路径”,这个时候,
如果边的长度是负的,就有可能产生更小的d[x]!而Dijkstra根本没有不会考虑 “把没在集合内的点加入路径”这种情况,这也就是Dijkstra算法目光短浅的原因。
再附上一个例子解释dijkstra不能算含负权边的单源最短路问题的原因
假设有一个图,其中A到B的权值为-2,B到C的权值为3,C到D的权值为1,
A到D的距离为1,如果我们使用Dijkstra算法从A点出发寻找到达D点的最短路径,
算法会首先选择A到B的路径,然后再选择B到C的路径,最后选择C到D的路径,
得到的总路径长度为(-2)+3+1=2。
然而,实际上存在一条更短的路径,即从A直接到D,路径长度为1。
这就是因为Dijkstra算法在处理负权图时,
无法正确识别出通过负权边可以获得更短路径的可能性,也就是贪心的局限性