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;
}