How many ways??
接下来的T行, 每行有三个整数 A, B, k, 表示问你从A 点到 B点恰好经过k个点的方案数 (k < 20), 可以走重复边。如果不存在这样的走法, 则输出0
当n, m都为0的时候输入结束
第一次接触这样的题,之前也不清楚矩阵可以这样使用。用A[i][j] = 1表示存在i到j的通路,令B = A * A,则B[i][j] = ∑A[i][k] * A[k][j],即从i到j经过两条边的路径数目(k为中转点,枚举k),同理,B * A为i到j经过3条边的路径数目,求k条边 ,二分求A^k.
#include"cmath"
#include"cstdio"
#include"cstring"
#include"iostream"
#include"algorithm"
using namespace std;
#define mod 1000
#define MAX 25
struct matrix
{
int mat[MAX][MAX];
};
matrix m,ans;
int maze[MAX][MAX];
matrix matrixmul(matrix a,matrix b)
{
matrix c;
for(int i = 0;i < MAX;i++)
{
for(int j = 0;j < MAX;j++)
{
c.mat[i][j] = 0;
for(int k = 0;k < MAX;k++)
{
c.mat[i][j] += a.mat[i][k] * b.mat[k][j];
}
c.mat[i][j] %= mod;
}
}
return c;
}
void quickpow(int x)
{
while(x)
{
if(x % 2)
{
ans = matrixmul(ans,m);
}
x /= 2;
m = matrixmul(m,m);
}
}
void initial()
{
for(int i = 0;i < MAX;i++)
{
for(int j = 0;j < MAX;j++)
{
ans.mat[i][j] = (i == j ? 1 : 0);
m.mat[i][j] = maze[i][j];
}
}
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m) && (n+m))
{
int s,t;
memset(maze,0,sizeof(maze));
while(m--)
{
scanf("%d%d",&s,&t);
maze[s][t] = 1;
}
int tt;
scanf("%d",&tt);
while(tt--)
{
int st,en,cnt;
initial();
scanf("%d%d%d",&st,&en,&cnt);
quickpow(cnt);
printf("%d\n",ans.mat[st][en]%mod);
}
}
return 0;
}