题目:http://acm.hdu.edu.cn/showproblem.php?pid=2157
把给定的图转为邻接矩阵,即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条边的路径数。
通过将矩阵连乘的过程模拟出来,模拟一遍就懂了。
#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
const ll mod = 1000;
const int maxn=22; //自己看情况定义
//定义矩阵乘法
struct matrix{
ll arr[maxn][maxn];
matrix operator*(matrix b){
matrix ans;
ll tmp;
for(int i=0; i<maxn; i++)
for(int j=0; j<maxn; j++){
ans.arr[i][j] = 0;
for(int k=0; k<maxn; k++){
tmp = (arr[i][k]*b.arr[k][j])%mod;
ans.arr[i][j] = (ans.arr[i][j] + tmp)%mod;
//cout<<"oh"<<endl;
}
}
return ans;
}
};
//矩阵快速幂
matrix quick_pow(matrix a,ll N){
matrix ans;
memset(ans.arr,0,sizeof(ans.arr));
for(int i=0; i<maxn; i++)
ans.arr[i][i] = 1;
while(N){
if(N&1)
ans = ans*a;
a = a*a;
N /= 2;;
}
return ans;
}
int main(){
matrix a;
int n,m;
while(scanf("%d%d",&n,&m)&&(n+m)){
memset(a.arr,0,sizeof(a.arr));
int x,y;
for(int i=0;i<m;i++){
scanf("%d%d",&x,&y);
a.arr[x][y]=1ll;
}
int t; ll k;
scanf("%d",&t);
for(int i=0;i<t;i++){
scanf("%d%d%lld",&x,&y,&k);
matrix ans=quick_pow(a,k);
printf("%d\n",ans.arr[x][y]);
}
}
return 0;
}