矩阵十大经典标题之八-hdu-2157-How many ways?

矩阵十大经典题目之八-hdu-2157-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<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
#define MOD 1000
struct matrix
{
    int mat[31][31];
    matrix(){memset(mat,0,sizeof(mat));}
};
int n;
matrix mul(matrix A,matrix B)
{
    int i,j,k;
    matrix C;
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=n;j++)
        {
            for(k=1;k<=n;k++)
            {
                C.mat[i][j]=(C.mat[i][j]+A.mat[i][k]*B.mat[k][j])%MOD;
            }
        }
    }
    return C;
}
matrix powmul(matrix A,int k)
{
    matrix B;
    for(int i=1;i<=n;i++)B.mat[i][i]=1;
    while(k)
    {
        if(k&1)B=mul(B,A);
        A=mul(A,A);
        k>>=1;
    }
    return B;
}
int main()
{
    int s,t,m,T,a,b,k;
    while(~scanf("%d%d",&n,&m)&&(n||m))
    {
        matrix A,B;
        while(m--)
        {
            scanf("%d%d",&s,&t);
            A.mat[s+1][t+1]=1;
        }
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d%d",&a,&b,&k);
            B=A;
            B=powmul(A,k);
            cout<<B.mat[a+1][b+1]<<endl;
        }
    }
    return 0;
}