n个点 m条路 询问T次 从a点走到b点刚好k步的方案数是多少
给定一个有向图,问从A点恰好走k步(允许重复经过边)到达B点的方案数mod p的值
把 给定的图转为邻接矩阵,即A(i,j)=1当且仅当存在一条边i->j。令C=A*A,那么C(i,j)=ΣA(i,k)*A(k,j),实际上就 等于从点i到点j恰好经过2条边的路径数(枚举k为中转点)。类似地,C*A的第i行第j列就表示从i到j经过3条边的路径数
Sample Input
4 4 // n m
0 1
0 2
1 3
2 3
2 //T
0 3 2 //a b k
0 3 3
3 6
0 1
1 0
0 2
2 0
1 2
2 1
2
1 2 1
0 1 3
0 0
Sample Output
2
0
1
3
1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 # include <algorithm> 5 # include <cmath> 6 # define LL long long 7 using namespace std ; 8 9 const int MOD = 1000 ; 10 int n ; 11 12 struct Matrix 13 { 14 LL mat[31][31]; 15 }; 16 17 Matrix mul(Matrix a,Matrix b) //矩阵乘法 18 { 19 Matrix c; 20 for(int i=0;i<n;i++) 21 for(int j=0;j<n;j++) 22 { 23 c.mat[i][j]=0; 24 for(int k=0;k<n;k++) 25 { 26 c.mat[i][j]=(c.mat[i][j] + a.mat[i][k]*b.mat[k][j])%MOD; 27 } 28 } 29 return c; 30 } 31 Matrix pow_M(Matrix a,int k) //矩阵快速幂 32 { 33 Matrix ans; 34 memset(ans.mat,0,sizeof(ans.mat)); 35 for (int i=0;i<n;i++) 36 ans.mat[i][i]=1; 37 Matrix temp=a; 38 while(k) 39 { 40 if(k&1)ans=mul(ans,temp); 41 temp=mul(temp,temp); 42 k>>=1; 43 } 44 return ans; 45 } 46 47 48 int main () 49 { 50 //freopen("in.txt","r",stdin) ; 51 int m ; 52 while(cin>>n>>m) 53 { 54 if (n == 0 && m == 0) 55 break ; 56 int i ; 57 Matrix A , B ; 58 int a ,b , k ; 59 memset(A.mat,0,sizeof(A.mat)); 60 for (i = 0 ; i < m ;i++) 61 { 62 cin>>a>>b ; 63 A.mat[a][b] = 1 ; 64 } 65 int T ; 66 cin>>T ; 67 while(T--) 68 { 69 cin>>a>>b>>k ; 70 B = pow_M(A,k) ; 71 cout<<B.mat[a][b]<<endl ; 72 } 73 } 74 75 return 0 ; 76 }
时间: 2024-10-22 09:55:06