HDU 2157 How many ways?? 【矩陣經典8】
阿新 • • 發佈:2018-11-13
任意門:http://acm.hdu.edu.cn/showproblem.php?pid=2157
How many ways??
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5339 Accepted Submission(s): 2109
接下來的T行, 每行有三個整數 A, B, k, 表示問你從A 點到 B點恰好經過k個點的方案數 (k < 20), 可以走重複邊。如果不存在這樣的走法, 則輸出0
當n, m都為0的時候輸入結束
Sample Input 4 4 0 1 0 2 1 3 2 3 2 0 3 2 0 3 3 3 6 0 1 1 0 0 2 2 0 1 2 2 1 2 1 2 1 0 1 3 0 0
Sample Output 2 0 1 3
題意概括:
給一個有向圖,問從A點恰好走k步(允許重複經過邊)到達B點的方案數(mod 1000)
解題思路:
把 給定的圖 D 轉為鄰接矩陣,即A(i,j)=1當且僅當存在一條邊 i->j。
則 A的 l 次冪 Al ( l >= 1) 中元素 aij(l) 為 D 中 vi -> vj 長度為 l 的通路數。
AC code:
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <cstring> 5 #include <cmath> 6 #define LL long long 7 #define Mod 1000 8 using namespace std; 9 const int MAXN = 101; 10 int N, M, T; 11 12 struct mat 13 { 14 int m[MAXN][MAXN]; 15 }base, tmp, ans; 16 17 mat muti(mat a, mat b) 18 { 19 mat res; 20 memset(res.m, 0, sizeof(res.m)); 21 22 for(int i = 0; i < N; i++) 23 for(int j = 0; j < N; j++) 24 { 25 if(a.m[i][j]){ 26 for(int k = 0; k < N; k++) 27 res.m[i][k] = (res.m[i][k] + a.m[i][j] * b.m[j][k])%Mod; 28 } 29 } 30 return res; 31 } 32 33 mat qpow(mat a, int n) 34 { 35 mat res; 36 memset(res.m, 0, sizeof(res.m)); 37 for(int i = 0; i < N; i++) res.m[i][i] = 1; 38 while(n){ 39 if(n&1) res = muti(res, a); 40 n>>=1; 41 a = muti(a, a); 42 } 43 return res; 44 } 45 46 int main() 47 { 48 int a, b, k; 49 while(~scanf("%d%d", &N, &M) && (N+M)){ 50 memset(base.m, 0, sizeof(base.m)); 51 for(int i = 1; i <= M; i++){ 52 scanf("%d%d", &a, &b); 53 base.m[a][b] = 1; 54 } 55 56 scanf("%d", &T); 57 while(T--){ 58 scanf("%d%d%d", &a, &b, &k); 59 ans = qpow(base, k); 60 printf("%d\n", ans.m[a][b]); 61 } 62 } 63 return 0; 64 }View Code