查看题干,可以发现数据有以下特点,这也说明了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]); } } } }
测试数据如下: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的距离,
floyd可以处理负边的原因很简单,因为我们是采用暴力枚举的方法,每个边仅算一次,但是当产生负权回路的时候就出问题了。
测试数据如下:
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