POJ3613 Cow Relays(矩阵快速幂)
题目大概要求从起点到终点恰好经过k条边的最短路。
离散数学告诉我们邻接矩阵的k次幂就能得出恰好经过k条路的信息,比如POJ2778。
这题也一样,矩阵的幂运算定义成min,而min满足结合律,所以可以用快速幂求解。
另外这题点的序号要离散化一下,最多也就200个点。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 #define INF (1<<29) 6 7 int N; 8 9 struct Mat{ 10 int m[222][222]; 11 Mat(){ 12 for(int i=0; i<222; ++i){ 13 for(int j=0; j<222; ++j) m[i][j]=INF; 14 } 15 } 16 }; 17 Mat operator*(const Mat &m1,const Mat &m2){ 18 Mat m; 19 for(int i=0; i<N; ++i){ 20 for(int j=0; j<N; ++j){ 21 for(int k=0; k<N; ++k){ 22 m.m[i][j]=min(m.m[i][j],m1.m[i][k]+m2.m[k][j]); 23 } 24 } 25 } 26 return m; 27 }; 28 29 int idx[1111]; 30 31 int main(){ 32 Mat m; 33 int n,t,s,e,a,b,c; 34 scanf("%d%d%d%d",&n,&t,&s,&e); 35 memset(idx,-1,sizeof(idx)); 36 while(t--){ 37 scanf("%d%d%d",&c,&a,&b); 38 if(idx[a]==-1){ 39 idx[a]=N++; 40 } 41 if(idx[b]==-1){ 42 idx[b]=N++; 43 } 44 m.m[idx[a]][idx[b]]=m.m[idx[b]][idx[a]]=c; 45 } 46 --n; 47 Mat ans=m; 48 while(n){ 49 if(n&1){ 50 ans=ans*m; 51 } 52 m=m*m; 53 n>>=1; 54 } 55 printf("%d",ans.m[idx[s]][idx[e]]); 56 return 0; 57 }