最短路径之Floyd算法
Floyd算法又称弗洛伊德算法,也叫做Floyd's algorithm,Roy–Warshall algorithm,Roy–Floyd algorithm, WFI algorithm。
Floyd算法是一种在有权图中(有确定的非负的权值,不能存在环路)查找最短路径的算法。该算法的一次简单执行可以找出任意结点之间的最短路径(尽管它没有返回路径的具体信息)。
思想:
Floyd算法通过比较图中任意两点间所有可能存在的路径长度得到最短路径长度。
我们定义一个函数shortestPath(i,j,k)代表从结点i到结点j的最短路径且路径上所有结点的编号均小于k。
两结点间最短路径只有两种情况:1、从结点i经过若干编号小于k的结点到达结点j;2、从结点i经过若干编号小于k+1的结点到达结点j。
其中若最短路径为第二种情况,则此事路径可以分割为两段:从结点i到结点k+1和从结点k+1到结点j,其中从结点i到结点k+1为最短路径,从结点k+1到结点j也为最短路径。
我们定义w(i,j)为结点i到结点j的边的距离,如果两结点之间没有变则w(i,j)为无穷大。
那么以下等式
shortPath(i,j,0)=w(i,j);
shortestPath(i,j,k+1)=min(shortestPaht(i,j,k),shortestPaht(i,k+1,k)+shortestPath(k+1,j,k))
伪代码如下:
let dist be a |V| × |V| array of minimum distances initialized to ∞ (infinity) for each vertex v dist[v][v] ← 0 for each edge (u,v) dist[u][v] ← w(u,v) // the weight of the edge (u,v) for k from 1 to |V| for i from 1 to |V| for j from 1 to |V| if dist[i][j] > dist[i][k] + dist[k][j] dist[i][j] ← dist[i][k] + dist[k][j] end if
C代码
#include <stdio.h> #define N 10//定义顶点个数 int arr[N][N];//定义二维数组,其初始值为该图的邻接矩阵 int main(){ int len; while(scanf("%d",&len)!=EOF){ for(int i=0;i<N;i++){ for(int j=0;j<N;j++){ arr[i][j]=-1;//初始化二维数组,因为floyd不存在负数权值,故我们使用-1代替无穷大 } } int i,j,c;//定义结点及权值 while(len--){ scanf("%d %d %d",&i,&j,&c);//输入边的两个结点及边的距离 arr[i][j]=arr[j][i]=c; } // for(int k=0;k<len;k++){ for(int i=0;i<len;i++){ for(int j=0;j<len;j++){ if(arr[i][k]==-1||arr[k][j]==-1)//如果两个之中有一个是无穷大,则必有arr[i][j]不能经过k结点联结 continue; if(arr[i][j]==-1||arr[i][k]+arr[k][j]<arr[i][j])//如果经过k结点后路径变短,则更新路径 arr[i][j]=arr[j][i]=arr[i][k]+arr[k][j]; } } } } return 0; }