在说bellman_ford算法前,先解释dijkstra算法的思想
我们用 dis[ ] 数组来存放 i 点到起点的最短距离
1、首先它是从起点开始,广度遍历,逐层更新,靠近起点的先被确定最终距离
2、如果我们要更新 dis[y] 的最短距离,则一定用比它距离要短的 dis[x] 来更新
如果dis[y]为全局最短,则dis[y] 不会再被更新,因为没有更短的 dis[x]值可以来更新它
3、那我们每次找全局最短的距离 dis[x] 来更新dis[y]
为什么dis[] 数组中最小的值就一定是i 点的最短距离
因为我们是从起点开始广度遍历,那么所有的未知点一定是由已知点进行更新的,即dis[ 未知点 ] > dis[已知点]
所以不会通过未知点再次更新已知点的距离,只用在已知点中找到最小的,即为最短距离
为什么一定要用全局最短?
全局最短的距离是确定的,不会再被更新,所以连上的边也是确定的,不会再被更改
如果不是全局最短,此时用此点( 设为u )去更新其他点,而u更新其他点(设为y)一次后,u就不会再次用来更新
而u再次被缩小时,y就不会再次更新
4、贪心求解,每次 dis[] 数组中更新后的值,不一定就是最优解
以一个例子做总结
假设此时 dis[v] 已经是全局最短,那么如果过v 点到达u点的最短距离也就确定
如果接下来是dis[x] 最短,那么过x 点到u 的最短距离也确定
接着是y。。。
u的最短距离即为它们的minn值
如果v确定后 dis[u] 为全局最短,说明dis[x] 和dis[y] 比dis[u] 长,自然就不用它们再更新
bellman_ford
思想:每次对所有的边进行松弛,每次可以确定一个点的最短距离,但不知道是哪个点,循环n-1,就可以确定所有的点
- 为什么每次松弛就可以确定一个点的最短距离?
其实与dijkstra一样的思想,只不过dijkstra是每次确定一个最短距离点,并用这个点去更新其他与之相连的边
而bellman_ford是每次更新所有的边,自然就包括最短距离点到与之相连边,那么每次也都是可以产生最短距离点,
只不过最短距离点并不知道是哪个点。并且,如果存在边权为负,最短距离点可能会再次更新
而dijkstra一旦确定最短距离点就不会再更改
- 为什么dijkstra不能处理负权边
此时1->3 的最短路应该为1-> 2 ->3, 而dijkstra 则在第一轮的遍历中就直接确定1->3 的最短距离为1,并且不会再更改
所以结果是错的
(对于环路,如果权值和为负,则每走一圈,最短距离就会缩小,如果回路权值和为正,多走一圈就会增加一圈的值)
spfa判断负环路
https://blog.csdn.net/forever_dreams/article/details/81161527