POJ--3613[Cow Relays] floyd 倍增法

 

POJ--3613[Cow Relays] floyd 倍增法

分类: 图论   253人阅读  评论(1)  收藏  举报
算法 c
 

题意:
给你一张无向图,求从S到E恰好经过N条边(可重复走)的最短路。

 

分析:

(1):根据Floyd算法的特殊性,它是通过插入点的方法来找到最短路的,特别适合此题,假如我们插入N-1个点,求到的则是经过N条边的最短路。假设我们每一次floyd只插入一个点的话,那么单步Floyd N次的话,则可以插入N个点。

(2):而N次floyd可以用倍增思想加速,就是自底向上的二分。类似求矩阵A^N。

(3):这里还有一点要注意,T的范围是(2~100),所以最多顶点只有200,而顶点标号的范围却(1 ≤ I1i ≤ 1,000; 1 ≤ I2i ≤ 1,000)。这样我们可以将编号离散化,开map时只需开到map[205][205],既节省了内存,又使所以结点的编号连续,加快了速度。

(4):还有一点比较郁闷,一开始INF是定义成99999999,不停的WA,改成100000001就AC了。。。囧。。。。。看来以后一定要往大开。。。。不然怎么死都不知道。。。唉

 

 

源代码:

[cpp]  view plain copy
  1. /*Floyd(倍增法)*/  
  2. /*N次Floyd*/  
  3. /*求从S到E恰好经过N条边(可重复走)的最短路。*/  
  4. /*AC代码:125ms*/  
  5. #include <iostream>  
  6. #define MAXN 210  
  7. #define INF 1000000000//注意,原来写99999999会WA!!!  
  8. int v[1005];//存那些牛的顶点(离散化)  
  9. int map[MAXN][MAXN];//存原地图  
  10. int ans[MAXN][MAXN];//存答案  
  11. int temp[MAXN][MAXN];//临时储存  
  12. int cnt;  
  13. int N,T,S,E;  
  14. void Init()  
  15. {  
  16.     int val,s,e,i,j;  
  17.     for(i=0;i<205;i++)//因为离散化后最多只有200个点  
  18.     {  
  19.         for(j=0;j<205;j++)  
  20.             map[i][j]=ans[i][j]=temp[i][j]=INF;  
  21.         ans[i][i]=0;  
  22.     }  
  23.     cnt=0;  
  24.     memset(v,0,sizeof(v));  
  25.     for(i=1;i<=T;i++)  
  26.     {  
  27.         scanf("%d%d%d",&val,&s,&e);  
  28.         if(v[s]==0)//连续化结点编号,提高运行效率  
  29.         {  
  30.             cnt++;  
  31.             v[s]=cnt;  
  32.         }  
  33.         if(v[e]==0)  
  34.         {  
  35.             cnt++;  
  36.             v[e]=cnt;  
  37.         }  
  38.         if(map[v[s]][v[e]]>val)  
  39.             map[v[s]][v[e]]=map[v[e]][v[s]]=val;  
  40.     }  
  41. }  
  42. void floyd(int a[MAXN][MAXN],int b[MAXN][MAXN],int c[MAXN][MAXN])  
  43. {  
  44.     int i,j,k;  
  45.     for(k=1;k<=cnt;k++)  
  46.         for(i=1;i<=cnt;i++)  
  47.             for(j=1;j<=cnt;j++)  
  48.                 if(a[i][j]>b[i][k]+c[k][j])  
  49.                     a[i][j]=b[i][k]+c[k][j];  
  50. }  
  51. void copy(int a[MAXN][MAXN],int b[MAXN][MAXN])  
  52. {  
  53.     int i,j;  
  54.     for(i=1;i<=cnt;i++)  
  55.         for(j=1;j<=cnt;j++)  
  56.         {  
  57.             a[i][j]=b[i][j];  
  58.             b[i][j]=INF;  
  59.         }  
  60. }  
  61. void work(int n)//N次Floyd  
  62. {  
  63.     while(n)  
  64.     {  
  65.         if(n&1)  
  66.         {  
  67.             floyd(temp,ans,map);//多出来的1先加到ans  
  68.             copy(ans,temp);  
  69.         }  
  70.         floyd(temp,map,map);  
  71.         copy(map,temp);  
  72.         n>>=1;  
  73.     }   
  74. }  
  75. int main()  
  76. {  
  77.     while(scanf("%d%d%d%d",&N,&T,&S,&E)!=EOF)  
  78.     {  
  79.         Init();  
  80.         work(N);  
  81.         printf("%d\n",ans[v[S]][v[E]]);  
  82.     }  
  83.     return 0;  
  84. }  

你可能感兴趣的:(图论)