矩阵十大经典题目之八 how many ways
开始学矩阵,借鉴了一些网上的文章,渐渐地去领会。这是第一题。加油!
题目大意:给定一个有向图,问从A点恰好走k步(允许重复经过边)到达B点的方案数mod p的值
把 给定的图转为邻接矩阵,即A(i,j)=1当且仅当存在一条边i->j。令C=A*A,那么C(i,j)=ΣA(i,k)*A(k,j),实际上就 等于从点i到点j恰好经过2条边的路径数(枚举k为中转点)。类似地,C*A的第i行第j列就表示从i到j经过3条边的路径数。同理,如果要求经过k步的 路径数,我们只需要二分求出A^k即可。
就是转化为矩阵,然后算矩阵的乘法。
#include<cstdio> #include<iostream> #include<cstring> #define mol 1000007 #define rep(i,j,k) for(int i = j; i <= k; i++) using namespace std; int m, n; struct maxtrix{ int mat[32][32]; maxtrix(){ memset(mat,0,sizeof(mat)); } }; int read() { int s = 0, t = 1; char c = getchar(); while( !isdigit(c) ){ if( c == '-' ) t = -1; c = getchar(); } while( isdigit(c) ){ s = s * 10 + c - '0'; c = getchar(); } return s * t; } maxtrix pow_mul(maxtrix x, maxtrix y) { maxtrix z; rep(i,1,m){ rep(j,1,m){ rep(k,1,m){ z.mat[i][j] = ( z.mat[i][j] + x.mat[i][k] * y.mat[k][j] )% mol; } } } return z; } maxtrix powl(maxtrix a,int k) { maxtrix b; rep(i,1,m) b.mat[i][i] = 1; while( k ){ if( k & 1 ) b = pow_mul(b,a); a = pow_mul(a,a); k >>= 1; } return b; } int main() { m = read(); n = read(); maxtrix a; rep(i,1,n){ int x = read(), y = read(); a.mat[x][y] = 1; } int t = read(); while( t-- ){ int x = read(), y = read(), k = read(); maxtrix b; b = powl(a,k); cout<<b.mat[x][y]<<endl; } return 0; }