• HDU2157 经典矩阵乘法


    题意

    给定一个有向图,问从A点恰好走k步(允许重复经过边)到达B点的方案数mod p的值

    分析

    将给定的图转化为0/1邻接矩阵,即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;
    }
    View Code

     

  • 相关阅读:
    VB.NET中获取串口列表
    跟着你混,真吃亏!
    [翻译]部署Microsoft .NET Framework Version 3.0(含下载)
    将特定格式的TXT数据文件写入EXCEL
    VB.NET中判断一个数组中是否有重值
    多语言应用程序开发
    .NET 环境下进制间的转换
    初识.NET
    映射Y轴
    Culture Name
  • 原文地址:https://www.cnblogs.com/Superwalker/p/8562323.html
Copyright © 2020-2023  润新知