floyd算法:可以有负权边,但不能有负权回路

Floyd求最短路

查看题干,可以发现数据有以下特点,这也说明了folyd算法适用条件。
图中可能存在重边和自环,边权可能为负数。数据保证图中不存在负权回路。

一、代码模板

void floyd(){
    for(int k=1;k<=n;k++){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
            }
        }
    }
}

1.1首先介绍为什么把k放最外层

测试数据如下:x,y,z代表着x点->y点 距离= 1

1 10 4 //点1到点10距离为4
10 9 2
9 7 3
...

假设1-7的最短路径为:1-10-9-7
d[1][9] = d[1][10] + d[10][7] = d[1][9]+d[9][7]
如果我们把k放最里,会发现当我们要求1-7的最小距离的时候,只能遍历
1-1-7,1-2-7,1-3-7,... ,1-n-7
会发现我们还没有遍历1-k-10,1-k-9,而当我们遍历到1-k-9(或1-k-10)的时候我们又没法更新1-7的距离,

1.2 我们再来介绍一下为什么可以处理负边

floyd可以处理负边的原因很简单,因为我们是采用暴力枚举的方法,每个边仅算一次,但是当产生负权回路的时候就出问题了。

1.3 当处理负权回路的时候产生的问题

测试数据如下:

1 2 -5
2 3 -3
3 1 -6

会发现1-3的距离变成了-22。
那么这个结果是怎么出现的呢?
1-k-3的结果产生来自三个地方:
1-1-3
1-2-3
1-3-3
拿1-3-3举例发现:1-3来自于1-2-3 = -8
3-3来自于3-1-3=INF,3-2-3=-14,当然当k=3,i=1,j=3还没有遍历到3-3-3
所以最短为-14-8=-22

二、floyd的应用

  • 求最短路径
  • 传递闭包
  • 找最小环
  • 恰好经过k条边的最短路(倍增)
posted @ 2021-09-12 10:15  徐行code  阅读(2250)  评论(0编辑  收藏  举报