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上的数据。。。其实我是自己懒得造数据。。。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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,以后就直接顺序输出路径了,逆序还得用一个数组来保存,麻烦。。。。