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