标签:矩阵
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2157
题目大意:给定一个有向图,问从A点恰好走k步(允许重复经过边)到达B点的方案数mod p的值
本来以为是DFS搜索,发现用矩阵也可以做!~ 好神奇。
把 给定的图转为邻接矩阵,即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<iostream> #include<cstring> #include<stdio.h> using namespace std; const int MAX = 32; int n,M=1000; struct Matrix { int v[MAX][MAX]; }; Matrix mtMul(Matrix A, Matrix B) // 求矩阵 A * B { int i, j, k; Matrix C; for(i = 0; i < n; i ++) for(j = 0; j < n; j ++) { C.v[i][j] = 0; for(k = 0; k < n; k ++) C.v[i][j] = (A.v[i][k] * B.v[k][j] + C.v[i][j]) % M; } return C; } Matrix mtPow(Matrix origin,int k) //矩阵快速幂 { int i; Matrix res; memset(res.v,0,sizeof(res.v)); for(i=0;i<n;i++) res.v[i][i]=1; while(k) { if(k&1) res=mtMul(res,origin); origin=mtMul(origin,origin); k>>=1; } return res; } void out(Matrix A) { for(int i=0;i<n;i++) { for(int j=0;j<n;j++) cout<<A.v[i][j]<<" "; cout<<endl; } cout<<endl; } int main () { int m; while(~scanf("%d%d",&n,&m)) { if(m==0&&n==0) break; Matrix A; memset(A.v,0,sizeof(A.v)); int s,e; while(m--) scanf("%d%d",&s,&e),A.v[s][e]=1; //out(A); int T; scanf("%d",&T); while(T--) { int ss,ee,kk; scanf("%d%d%d",&ss,&ee,&kk); Matrix B; B=mtPow(A,kk); cout<<B.v[ss][ee]<<endl; } } }
矩阵十题【九】 HDU 2157 How many ways??,布布扣,bubuko.com
矩阵十题【九】 HDU 2157 How many ways??
标签:矩阵
原文地址:http://blog.csdn.net/u010468553/article/details/38493629