poj 3613 Cow Relays (矩阵乘法的变形 floyd 倍增法)

http://poj.org/problem?id=3613

 


题意:

求从一个点s 到 一点 e 经过 n 条边的最短路经是多少(可以有重边):

看到很难多解题报告说的是n 个点 ,其实,n 条边 应该是 n - 1 个点

题解:

 

我们知道线性代数中有: 在只 含有 01邻接矩阵 AK次 方 C=A^KC[i][j]表示 i点到 j点正好经过 K条边的路径数。

 

而floyd则是每次使用一个中间点k去更新i,j之间的距离,那么更新成功表示i,j之间恰有一个点k时的最短路,如果做N - 1次floyd那么不就是i,j之间借助N - 1 个点时的最短路了

当 c[i][j] > a[i][k] + a[k][j]  则更新

第二次将c[i][j]拷贝回到a[i][j]当中,并将c[i][j]重新置为INF,再做一次,则是在原来的基础上在i,j之间再用一个点k来松弛,这时候i,j之间实际上已经是两个点了,

但是这个题的   n (边数太大)我们要用到 倍增法,其实即使 二分思想  例如  经过 5  条边 把  (4 个点)  ==  两个 2 条边的  松驰一次 ;


  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cmath>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include< set>
  7 #include<map>
  8 #include<queue>
  9 #include<vector>
 10 #include< string>
 11  #define Min(a,b) a<b?a:b
 12  #define Max(a,b) a>b?a:b
 13  #define CL(a,num) memset(a,num,sizeof(a));
 14  #define maxn  40
 15  #define eps  1e-6
 16  #define inf 100000000
 17  #define mx 1<<60
 18  #define ll   __int64
 19  using  namespace std;
 20 map< int , int>map1;
 21  int num ;
 22  struct matrix
 23 {
 24      int m[ 210][ 210];
 25      void clear()
 26     {
 27         memset(m, 0x3f, sizeof(m));//错在这好几次 ,貌似这道题的 数很大 我的 inf  开的不够大
 28         /* for(int i = 0; i < 210 ;i++)
 29         {
 30             for(int  j = 0 ; j < 210 ;j++)
 31                 m[i][j] = inf;
 32         } */
 33     }
 34 };
 35 
 36  matrix floyd(matrix a,matrix b)
 37 {
 38 
 39     matrix dis;
 40     dis.clear();
 41      int i,j,k;
 42      for(k =  0; k < num;k++)//一次floyd  是找到一个中间点
 43      for(i =  0 ; i < num;i++ )
 44     {
 45          for(j =  0;j < num;j++)
 46         {
 47 
 48              if(dis.m[i][j] > a.m[i][k] + b.m[k][j])
 49             {
 50                  dis.m[i][j] = a.m[i][k] + b.m[k][j] ;
 51                   // printf("%d %d %d  ++++\n",dis.m[i][j],i , j);
 52 
 53 
 54             }
 55 
 56         }
 57     }
 58 
 59      return dis;
 60 }
 61 matrix  solve(matrix a, int k)
 62 {
 63      if(k ==  0return  a;
 64     matrix ans ;
 65 
 66     ans = a ;
 67 
 68      while(k)
 69     {
 70 
 71          if(k& 1)
 72         {
 73             ans = floyd(ans,a);
 74 
 75         }
 76         a = floyd(a,a);
 77 
 78 
 79         k>>= 1;
 80     }
 81      return ans ;
 82 }
 83  int main()
 84 {
 85      int t,n,m,s,e,x,y,len,i;
 86     matrix a;
 87      while(scanf( " %d%d%d%d ",&n,&t,&s,&e)!=EOF)
 88     {
 89          num =  0;
 90          map1.clear() ;
 91          a.clear() ;
 92 
 93          for(i =  0; i < t;i++)
 94         {
 95             scanf( " %d %d %d ",&len,&x,&y);
 96              if(map1.find(x)==map1.end()) map1[x] = num ++;
 97              if(map1.find(y)==map1.end()) map1[y] = num ++;
 98              int x1 = map1[x];
 99              int y1 = map1[y];
100 
101              if(len < a.m[x1][y1])
102             {
103 
104                 a.m[x1][y1] = a.m[y1][x1] = len ;
105 
106 
107             }
108 
109 
110         }
111 
112           int  j;
113 
114 
115           a = solve(a,n -  1);// n 条边  ,经过 n-1 个点
116 
117            /* for(i = 0; i < num;i++)
118           {
119               for(j = 0; j < num;j++)
120            {
121                printf("%d ",a.m[i][j]);
122            }
123 
124               printf("\n");
125 
126           } */
127 
128         printf( " %d\n ",a.m[map1[s]][map1[e]]) ;
129 
130     }
131 }

 

 

 

 

 

 

你可能感兴趣的:(floyd)