POJ 3613 FLOYD+倍增
题意:
求S到T的经过k条路径的最短路
(这题出的真心好)
思路:
设d[i][j][k]为从i到j经过k条边的最短路,则d[i][j][k]=d[i][p][k/2]+d[p][j][k/2]
利用倍增加速floyd
其实说实话矩阵乘法和floyd真心很像,直接写成矩阵乘法的格式了~
PS:读入边的时候,第一个元素是边权,我纠结了半天,怎么看图也不连通。。。。
View Code
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <iostream> 5 #include <map> 6 7 #define N 200 8 9 using namespace std; 10 11 map<int,int> mp; 12 13 struct MATRIX 14 { 15 int mt[N][N]; 16 }dg,fb; 17 18 int n,m,S,T,cnt; 19 20 inline MATRIX operator +(MATRIX a,MATRIX b) 21 { 22 MATRIX c; 23 memset(c.mt,0x3f,sizeof c.mt); 24 for(int k=1;k<=cnt;k++) 25 for(int i=1;i<=cnt;i++) 26 for(int j=1;j<=cnt;j++) 27 if(c.mt[i][j]>a.mt[i][k]+b.mt[k][j]) 28 c.mt[i][j]=a.mt[i][k]+b.mt[k][j]; 29 return c; 30 } 31 32 void read() 33 { 34 mp.clear(); cnt=0; 35 memset(dg.mt,0x3f,sizeof dg.mt); 36 memset(fb.mt,0x3f,sizeof fb.mt); 37 for(int i=1,a,b,sa,sb,sd;i<=m;i++) 38 { 39 scanf("%d%d%d",&sd,&sa,&sb); 40 if(!mp[sa]) mp[sa]=++cnt; 41 if(!mp[sb]) mp[sb]=++cnt; 42 a=mp[sa]; b=mp[sb]; 43 if(sd<dg.mt[a][b]) dg.mt[b][a]=dg.mt[a][b]=sd; 44 } 45 for(int i=1;i<=cnt;i++) fb.mt[i][i]=0; 46 } 47 48 void go() 49 { 50 while(n)//倍增 51 { 52 if(n&1) fb=fb+dg; 53 dg=dg+dg; 54 n>>=1; 55 } 56 printf("%d\n",fb.mt[mp[S]][mp[T]]); 57 } 58 59 int main() 60 { 61 62 while(scanf("%d%d%d%d",&n,&m,&S,&T)!=EOF) 63 { 64 read(); 65 go(); 66 } 67 return 0; 68 }
没有人能阻止我前进的步伐,除了我自己!