5 0 3 22 -1 4 3 0 5 -1 -1 22 5 0 9 20 -1 -1 9 0 4 4 -1 20 4 0 5 17 8 3 1 1 3 3 5 2 4 -1 -1 0
From 1 to 3 : Path: 1-->5-->4-->3 Total cost : 21 From 3 to 5 : Path: 3-->4-->5 Total cost : 16 From 2 to 4 : Path: 2-->1-->5-->4 Total cost : 17
floyd算法
1.定义概览
Floyd-Warshall算法(Floyd-Warshall algorithm)是解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径问题,同时也被用于计算有向图的传递闭包。Floyd-Warshall算法的时间复杂度为O(N3),空间复杂度为O(N2)。
2.算法描述
1)算法思想原理:
Floyd算法是一个经典的动态规划算法。用通俗的语言来描述的话,首先我们的目标是寻找从点i到点j的最短路径。从动态规划的角度看问题,我们需要为这个目标重新做一个诠释(这个诠释正是动态规划最富创造力的精华所在)
从任意节点i到任意节点j的最短路径不外乎2种可能,1是直接从i到j,2是从i经过若干个节点k到j。所以,我们假设Dis(i,j)为节点u到节点v的最短路径的距离,对于每一个节点k,我们检查Dis(i,k) + Dis(k,j) < Dis(i,j)是否成立,如果成立,证明从i到k再到j的路径比i直接到j的路径短,我们便设置Dis(i,j) = Dis(i,k) + Dis(k,j),这样一来,当我们遍历完所有节点k,Dis(i,j)中记录的便是i到j的最短路径的距离。
2).算法描述:
a.从任意一条单边路径开始。所有两点之间的距离是边的权,如果两点之间没有边相连,则权为无穷大。
b.对于每一对顶点 u 和 v,看看是否存在一个顶点 w 使得从 u 到 w 再到 v 比己知的路径更短。如果是更新它。
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define INF 0x3f3f3f3f int Map[110][110],path[110][110]; int p[110]; int n; void floyd() { int dk; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ path[i][j]=j; } } for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ for(int k=1;k<=n;k++){ dk=Map[j][i]+Map[i][k]+p[i]; if(dk < Map[j][k]){ Map[j][k]=dk; path[j][k]=path[j][i]; } else if(dk==Map[j][k]){ if(path[j][k] > path[j][i]) path[j][k]=path[j][i]; } } } } } int main() { int x; while(~scanf("%d",&n)){ if(n==0) break; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ scanf("%d",&x); if(x==-1) Map[i][j]=INF; else Map[i][j]=x; } } for(int i=1;i<=n;i++) scanf("%d",&p[i]); floyd(); int sx,ed; while(scanf("%d%d",&sx,&ed)!=EOF){ if(sx==-1 && ed==-1) break; printf("From %d to %d :\nPath: %d",sx,ed,sx); x=sx; while(x!=ed){ printf("-->%d",path[x][ed]); x=path[x][ed]; } printf("\nTotal cost : %d\n\n",Map[sx][ed]); } } return 0; }