题解
用一个矩阵来表示一个图的边的存在性,即矩阵C【i,j】=1表示有一条从i到j的有向边C【i,j】=0表示没有从i到j的边。这个矩阵的k次方后C【i,j】就表示有多少条从i到j恰好经过k条边的路径。
在此题中我们赋予边权值并把矩阵乘法中的+改为min这样这个矩阵的k次方后C【i,j】就表示从i到j恰好经过k条边的最短路径。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 const int N=300; 8 int n,t,s,e,u[N],v[N],w[N],b[N],a[N],ma[3000],num,tot; 9 struct jz{ 10 int a[N][N]; 11 }x; 12 jz jzc(jz a,jz b){ 13 jz c; 14 for(int i=1;i<=num;i++) 15 for(int j=1;j<=num;j++){ 16 c.a[i][j]=999999999; 17 } 18 for(int i=1;i<=num;i++) 19 for(int j=1;j<=num;j++) 20 for(int k=1;k<=num;k++){ 21 c.a[i][j]=min(c.a[i][j],a.a[i][k]+b.a[k][j]); 22 } 23 return c; 24 } 25 jz ksm(jz a,int k){ 26 jz ans=a; 27 k--; 28 while(k){ 29 if(k&1){ 30 ans=jzc(ans,a); 31 } 32 k>>=1; 33 a=jzc(a,a); 34 } 35 return ans; 36 } 37 int main(){ 38 scanf("%d%d%d%d",&n,&t,&s,&e); 39 for(int i=1;i<=t;i++){ 40 scanf("%d%d%d",&w[i],&u[i],&v[i]); 41 a[++tot]=u[i]; 42 b[tot]=u[i]; 43 a[++tot]=v[i]; 44 b[tot]=v[i]; 45 } 46 sort(b+1,b+1+tot); 47 num=unique(b+1,b+1+tot)-(b+1); 48 for(int i=1;i<=tot;i++){ 49 ma[a[i]]=lower_bound(b+1,b+1+num,a[i])-b; 50 } 51 for(int i=1;i<=num;i++) 52 for(int j=1;j<=num;j++) 53 x.a[i][j]=999999999; 54 for(int i=1;i<=t;i++){ 55 x.a[ma[u[i]]][ma[v[i]]]=min(x.a[ma[u[i]]][ma[v[i]]],w[i]); 56 x.a[ma[v[i]]][ma[u[i]]]=min(x.a[ma[v[i]]][ma[u[i]]],w[i]); 57 } 58 x=ksm(x,n); 59 printf("%d",x.a[ma[s]][ma[e]]); 60 return 0; 61 } 62 /* 63 2 6 6 4 64 11 4 6 65 4 4 8 66 8 4 9 67 6 6 8 68 2 6 9 69 3 8 9 70 */