HDU - 2157 - 鄰接矩陣k條路定理 - 矩陣快速冪
阿新 • • 發佈:2020-10-12
傳送門
離散書裡有一個定理,從一個點到另一個點走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\n", 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; }