题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2157
题意:有一个有向图,含有n个节点,m条边,Q个询问,每个询问有 s,t,p,求 s 到 t 经过 p 个点(这 p 个点包括 t 点,不包括 s 点)的所有方案数对100求余;
我们知道floyd算法中(i, j)是可以由(i,k)和(k,j)得到;那么就是经过k这个中间节点;这样一来就是 i -- k -- j 经过两个节点(k,j)所以从 i 到 j 经过2个点的方案总数是 (i,j)= ∑(i,k)*(k,j);(枚举所有的
k )然而这个正是矩阵(A*A)相乘的结果
以此类推经过3个点,4个点...p个点所求就是A^p中的(s, t);
#include <cstdio> #include <cstring> #include <iostream> #include <cmath> #include <map> #include <vector> #include <algorithm> #include <string> using namespace std; #define N 50 #define MOD 1000 #define met(a, b) memset(a, b, sizeof(a)) #define INF 0x3f3f3f3f typedef long long LL; struct Matrix { int a[N][N]; Matrix() { memset(a, 0, sizeof(a));///注意初始化; } }; int n, m; Matrix Mul(Matrix p, Matrix q) { Matrix temp;///注意初始化; for(int i=0; i<n; i++) { for(int j=0; j<n; j++) { for(int k=0; k<n; k++) temp.a[i][j] = (temp.a[i][j] + p.a[i][k]*q.a[k][j]) % MOD; } } return temp; } Matrix Pow(Matrix Matrix0, int k) { Matrix temp, Matrix1 = Matrix0; for(int i=0; i<N; i++) temp.a[i][i] = 1;///注意初始化; while(k) { if(k%2 == 1) temp = Mul(temp, Matrix1); Matrix1 = Mul(Matrix1, Matrix1); k /= 2; } return temp; } int main() { int u, v, k, Q; while(scanf("%d %d", &n, &m), m+n) { Matrix Matrix0; for(int i=1; i<=m; i++) { scanf("%d %d", &u, &v); Matrix0.a[u][v] = 1; } scanf("%d", &Q); while(Q--) { scanf("%d %d %d", &u, &v, &k); Matrix answer = Pow(Matrix0, k); printf("%d ", answer.a[u][v]); } } return 0; }