什么是Floyd算法
佛洛伊德是最简单的最短路径算法,可以计算图中任意两点间的最短路径。时间复杂度为O(N3),适用于出现负边权的情况。
怎么用代码实现?
算法描述:
( a )初始化:点u、v如果有边相连,则dis[u][v]=w[u][v]
如果不相连,则dis[u][v]=0x3f
( b )模板:
for(k=1;k<=n;k++){
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
if(dis[i][j]>dis[i][k]+dis[k][j])
dis[i][j]=dis[i][k]+dis[k][j];
}
}
}
( c )算法结束:dis[i][j]得出的就是任意起点i到任意终点j的最短路径。
疑问:为什么枚举中间点的循环k要放在最外层?
可以从一定不经过k点与一定经过k点的三维数组比较中推导出来
使用Floyd输出最短路径序列
Floyd算法输出路径也是采用记录前驱点的方式。因为floyd是计算任意两点间最短路径的算法,dis[i][j]记录从i到j的最短路径值。故我们定义pre[i][j]为一个二维数组,记录从i到j的最短路径中,j的前驱点是哪一个。递归还原路径。
初始化pre[N][N]为0,输入相连边时,重置相连边尾结点的前驱
若有无向边:pre[a][b]=a; pre[b][a]=b;
更新若floyd最短路有更新,那么pre[i][j]=pre[k][j];(这能不能直接赋值k的值?)
递归输出指两点s,e的最短路,先输出起点s,再将终点e放入递归,输出s+1~e的所有点。
void print(int x){
if(pre[s][x]==0) return;
print(pre[s][x]);
printf(“->%d”,x);
}
例题板题
① 最短路径问题
平面上有n个点(n<=100),每个点的坐标均在-10000~10000之间。其中的一些点之间有连线。若有连线,则表示可从一个点到达另一个点,即两点间有通路,通路的距离为两点间的直线