您的位置:首页 > 其它

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

2015-05-29 21:10 405 查看

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

 

# include <iostream>
# include <cstdio>
# include <cstring>
# include <algorithm>
# include <cmath>
# define LL long long
using namespace std ;

const int MOD = 1000 ;
int n ;

struct Matrix
{
LL mat[31][31];
};

Matrix mul(Matrix a,Matrix b) //矩阵乘法
{
Matrix c;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
c.mat[i][j]=0;
for(int k=0;k<n;k++)
{
c.mat[i][j]=(c.mat[i][j] + a.mat[i][k]*b.mat[k][j])%MOD;
}
}
return c;
}
Matrix pow_M(Matrix a,int k)  //矩阵快速幂
{
Matrix ans;
memset(ans.mat,0,sizeof(ans.mat));
for (int i=0;i<n;i++)
ans.mat[i][i]=1;
Matrix temp=a;
while(k)
{
if(k&1)ans=mul(ans,temp);
temp=mul(temp,temp);
k>>=1;
}
return ans;
}

int main ()
{
//freopen("in.txt","r",stdin) ;
int m ;
while(cin>>n>>m)
{
if (n == 0 && m == 0)
break ;
int i ;
Matrix A , B ;
int a ,b , k ;
memset(A.mat,0,sizeof(A.mat));
for (i = 0 ; i < m ;i++)
{
cin>>a>>b ;
A.mat[a][b] = 1 ;
}
int T ;
cin>>T ;
while(T--)
{
cin>>a>>b>>k ;
B = pow_M(A,k) ;
cout<<B.mat[a][b]<<endl ;
}
}

return 0 ;
}
View Code

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: