Floyd-Warshall可以比较高效地解决图论中多源最短路径的问题。它的本质是一次标号法动态规划——正因为如此,这个算法的实现有了非常难能可贵的一点,那就是它的简洁。所以很多人在求最单源短路的时候都会用它,而不是效率更高但实现略烦的Dijkstra或者Bellman-Ford(当然是在时间比较宽裕的时候啦!)。
总之,Floyd-Warshall算法好!来,跟我一起念——Flo-yd-算-法-好!呵呵,功能强大,携带方便,的确是杀人越货之利器呀。
DP的动态转移方程:
Dis[i,j]=w(i,j) w(i,j)当然就是图里的边权。
Dis[i,j]=min{ Dis[i,k]+Dis[k,j] | i<=k<=j } 简单。。
dis[i,j]表示i和j之间的最短路。
来看看这个演示代码吧。
#include
<
stdio.h
>
#define NV 5
#define MA 9999999
int main( void )
... {
int graph[NV][NV]=
...{
MA, 1, 7, 2, 8,
1, MA, 3, 2, 2,
7, 3, MA, 4, 4,
2, 2, 4, MA, 3,
8, 2, 4, 3, MA
};
int num=NV;
int path[NV][NV];
int i,j,k;
for(i=0;i<num;i++)...{
for(j=0;j<num;j++)
printf("%d ",graph[i][j]);
printf(" ");
}system("pause");
memset(path,0,sizeof(path));
for(i=0;i<num;i++)
for(j=0;j<num;j++)
path[i][j]=MA;
for(i=0;i<num;i++)...{
for(j=0;j<num;j++)...{
path[i][j]=graph[i][j];
}
}
for(k=0;k<num;k++)
for(i=0;i<num;i++)
for(j=0;j<num;j++)
if(path[i][j]>graph[i][k]+graph[k][j])
path[i][j]=graph[i][k]+graph[k][j];
for(i=0;i<num;i++)
for(j=0;j<num;j++)
printf("Shortest distance between <%d,%d>: %d ",i+1,j+1,path[i][j]);
system("pause");
return 0;
}
#define NV 5
#define MA 9999999
int main( void )
... {
int graph[NV][NV]=
...{
MA, 1, 7, 2, 8,
1, MA, 3, 2, 2,
7, 3, MA, 4, 4,
2, 2, 4, MA, 3,
8, 2, 4, 3, MA
};
int num=NV;
int path[NV][NV];
int i,j,k;
for(i=0;i<num;i++)...{
for(j=0;j<num;j++)
printf("%d ",graph[i][j]);
printf(" ");
}system("pause");
memset(path,0,sizeof(path));
for(i=0;i<num;i++)
for(j=0;j<num;j++)
path[i][j]=MA;
for(i=0;i<num;i++)...{
for(j=0;j<num;j++)...{
path[i][j]=graph[i][j];
}
}
for(k=0;k<num;k++)
for(i=0;i<num;i++)
for(j=0;j<num;j++)
if(path[i][j]>graph[i][k]+graph[k][j])
path[i][j]=graph[i][k]+graph[k][j];
for(i=0;i<num;i++)
for(j=0;j<num;j++)
printf("Shortest distance between <%d,%d>: %d ",i+1,j+1,path[i][j]);
system("pause");
return 0;
}