Dijkstra 和 Bellman-Ford算法以及spfa判断负环路

    xiaoxiao2025-02-01  47

    在说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

    最新回复(0)