hdu 2157 从a点走到b点刚好k步的方案数是多少 (矩阵快速幂)

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 }
View Code

 

posted @ 2015-05-29 21:10  __Meng  阅读(1157)  评论(0编辑  收藏  举报