传送门
离散书里有一个定理,从一个点到另一个点走k条路的方案数,求出邻接矩阵的k次方,最后邻接矩阵的答案就是方案数。
题目说的有问题。
在给定的有向图里,可能存在一个点到另一个点存在多条道路,但是只能算一次。
#include <iostream>
#include <cstdio>
#include <cstring>
#define ll long long
using namespace std;
const int N = 23;
const int mod = 1000;
struct Matrix{
int n, m;
ll a[N][N];
Matrix (int n = 0, int m = 0) : n(n),m(m){memset(a, 0, sizeof(a));}
Matrix operator * (const Matrix &b) const {
Matrix ans(n, b.m);
for(int i = 0; i < n; i++) {
for(int j = 0; j < b.m; j++) {
for(int k = 0; k < m; k++) {
ans.a[i][j] = (ans.a[i][j] + a[i][k] * b.a[k][j] % mod) % mod;
}
}
}
return ans;
}
};
Matrix ksm(Matrix a, ll b){
Matrix ans(a.n, a.m);
for(int i = 0; i < max(a.n, a.m); i++) ans.a[i][i] = 1;
while(b) {
if(b & 1) ans = ans * a;
a = a * a;
b >>= 1;
}
return ans;
}
ll a[N][N];
int n, m;
void solve(int aa, int bb, int k){
Matrix base(n, n);
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
base.a[i][j] = a[i][j];
base = ksm(base, k);
printf("%lld
", base.a[aa][bb]);
}
int main(){
while(~scanf("%d%d", &n, &m)){
if(n == 0 && m == 0) break;
memset(a, 0, sizeof(a));
for(int i = 1; i <= m; i++) {
int u, v;
scanf("%d%d", &u, &v);
a[u][v] = 1;
}
int t; scanf("%d", &t);
while(t--) {
int a, b, k;
scanf("%d%d%d", &a, &b, &k);
solve(a, b, k);
}
}
return 0;
}