题目:http://poj.org/problem?id=3613
题意就是求从起点到终点的一条恰好经过k条边的最短路;
floyd+矩阵快速幂,矩阵中的第i行第j列表示从i到j的最短路,矩阵本身代表一个边数状态;
所以矩阵相乘就是floyd算法,两个矩阵相乘就得到它们所代表的边数相加边数的状态矩阵;
原始矩阵自乘k-1次,过程中取min,就得到答案;
因为只是自乘,所以可以使用快速幂。
代码如下:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; int n,cnt,s,t,k,nd[1005]; int rd() { char dc; int x=0,f=1;dc=getchar(); while(dc<'0'||dc>'9') { if(dc=='-')f=-1; dc=getchar(); } while(dc>='0'&&dc<='9') { x=x*10+(dc-'0'); dc=getchar(); } return x*f; } struct Matrix{ int a[205][205]; Matrix operator * (const Matrix &y) const { Matrix x; memset(x.a,0x3f,sizeof x.a); for(int i=1;i<=cnt;i++) for(int j=1;j<=cnt;j++) for(int k=1;k<=cnt;k++) x.a[i][j]=min(x.a[i][j],a[i][k]+y.a[k][j]); return x; } }sid,ans; int main() { k=rd();n=rd();s=rd();t=rd(); memset(sid.a,0x3f,sizeof sid.a);// for(int i=1;i<=n;i++) { int x,y,z; z=rd();x=rd();y=rd(); if(!nd[x])nd[x]=++cnt; if(!nd[y])nd[y]=++cnt; sid.a[nd[x]][nd[y]]=sid.a[nd[y]][nd[x]]=z; } k--;//已经有连了一条边的矩阵 ans=sid;//同上意义 while(k) { // if(k&1)ans+=sid.a[nd[s]][nd[t]];//不是普通加法 if(k&1)ans=ans*sid; sid=sid*sid; k>>=1; } printf("%d",ans.a[nd[s]][nd[t]]); return 0; }