floyd 算法的个人理解

在做过hdu 1358之后,若菜对floyd也有了更深的理解,学过数据结构的都知道,floyd是用于求每一对顶点之间的最短距离(当然你也可以用dijkstra来求,只不过floyd形式更简单)。。。好吧,先说说我的理解吧,其实floyd本质上还是dp,如果要求顶点vi到顶点vj的距离,那么,我们可以在vi,vj之间引入一个最大点vk,通过vk求出vi到vj的距离的最小值,当然1<=vk<=n(假设有n个顶点),然后更新就行了。。。。然后就是路径的保存了,一般用path[i][j]来保存vi到vj的路径的上到达顶点vj的前一个点。。。然后我在做1538这道题的时候,突然发现其实我们也可以用path[i][j]来保存顶点vi到vj路径上的vi的后一个顶点。。。

好吧,下面的测试数据来自hdu 1538上的数据。。。其实我是自己懒得造数据。。。

View Code
 1 #include<iostream>

 2 const int N=100;

 3 const int inf=100000000;

 4 using namespace std;

 5 

 6 int cost[N];

 7 int edge[N][N];

 8 int path[N][N];

 9 int n,v0,v;

10 

11 //逆序输出

12 void floyd1(){

13     for(int k=1;k<=n;k++){

14         for(int i=1;i<=n;i++){

15             for(int j=1;j<=n;j++){

16                 if(cost[k]+edge[i][k]+edge[k][j]<edge[i][j]){

17                     edge[i][j]=edge[i][k]+edge[k][j]+cost[k];

18                     path[i][j]=path[k][j];//这个与初始化对应,此时path保存的就是vi->vj路径上的vj的前一个顶点

19                 }

20             }

21         }

22     }

23     int k=v;

24     printf("%d ",k);

25     while(path[v0][k]!=v0){

26         k=path[v0][k];

27         printf("%d ",k);

28     }

29     printf("%d\n",path[v0][k]);

30 }

31 //顺序输出

32 void floyd2(){

33     for(int k=1;k<=n;k++){

34         for(int i=1;i<=n;i++){

35             for(int j=1;j<=n;j++){

36                 if(cost[k]+edge[i][k]+edge[k][j]<edge[i][j]){

37                     edge[i][j]=edge[i][k]+edge[k][j]+cost[k];

38                     path[i][j]=path[i][k];//此时path保存的是vi->vj的路径上的起点

39                 }

40             }

41         }

42     }

43     int k=v0;

44     printf("%d ",k);

45     while(path[k][v]!=v){

46         k=path[k][v];

47         printf("%d ",k);

48     }

49     printf("%d\n",path[k][v]);

50 }

51 

52 int main(){

53     while(scanf("%d",&n)!=EOF){

54         for(int i=1;i<=n;i++){

55             for(int j=1;j<=n;j++){

56                 scanf("%d",&edge[i][j]);

57                 //path[i][j]=i;//如果初始化为i的话,如果想要保存路径,后面更新的时候,必须用path[i][j]=path[k][j];此时path保存的即为逆序

58                 path[i][j]=j;

59                 if(edge[i][j]==-1){

60                     edge[i][j]=inf;

61                 }

62             }

63         }

64         for(int i=1;i<=n;i++){

65             scanf("%d",&cost[i]);

66         }

67         while(scanf("%d%d",&v0,&v)==2){

68             if(v0==-1&&v==-1)break;

69         //    floyd1();

70             floyd2();

71         }

72     }

73     return 0;

74 }

好吧,我好好的想了一下,确实也是,由于path是二维数组,似乎有两种选择也不为怪吧。。。

orz,以后就直接顺序输出路径了,逆序还得用一个数组来保存,麻烦。。。。

你可能感兴趣的:(floyd)