题意:春天到了, HDU校园里开满了花, 姹紫嫣红, 非常美丽. 葱头是个爱花的人, 看着校花校草竞相开放, 漫步校园, 心情也变得舒畅. 为了多看看这迷人的校园, 葱头决定, 每次上课都走不同的路线去教室, 但是由于时间问题, 每次只能经过k个地方, 比方说, 这次葱头决定经过2个地方, 那他可以先去问鼎广场看看喷泉, 再去教室, 也可以先到体育场跑几圈, 再到教室. 他非常想知道, 从A 点恰好经过k个点到达B点的方案数, 当然这个数有可能非常大, 所以你只要输出它模上1000的余数就可以了. 你能帮帮他么?? 你可决定了葱头一天能看多少校花哦(翻译的6不6)
想法:用01矩阵存图,设i,j,k点,则矩阵自乘时会有此式子:mat[i][k]*mat[k][j],显然当i到k有路且k到j有路时才会使得它的解为1。那么mat的01矩阵从原来的图的存图矩阵变成了方案数矩阵了,如果i到k有mat[i][k]种方案,k到j有mat[k][j]种方案,那么i到j的方案显然是它俩相乘。
#include<iostream> #include<cstring> #include<cstdio> #define mod 1000 using namespace std; int n,m; struct node { int m[25][25]; }Mat,P,I; node matmul(node a,node b) { node c; for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { c.m[i][j]=0; for(int k=0;k<n;k++) { c.m[i][j]+=(a.m[i][k]*b.m[k][j])%mod; } c.m[i][j]%=mod; } } return c; } node quickpow(int num) { node k=P,res=I; while(num>=1) { if(num&1) { res=matmul(res,k); } num=num>>1; k=matmul(k,k); } return res; } int main() { while(~scanf("%d%d",&n,&m),n+m) { memset(P.m,0,sizeof(P.m)); for(int i=1;i<=m;i++) { int a,b; scanf("%d%d",&a,&b); P.m[a][b]=1; } for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { I.m[i][j]=(i==j); } } int q; node res; scanf("%d",&q); for(int i=1;i<=q;i++) { int a,b,c; scanf("%d%d%d",&a,&b,&c); res=quickpow(c); printf("%d\n",res.m[a][b]); } } return 0; }