• bzoj1297 [SCOI2009]迷路——拆点+矩阵快速幂


    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1297

    一看感觉是矩阵快速幂之类的,但边权不好处理啊;

    普通的矩阵快速幂只能处理边权为1的,所以想办法把边权处理成1;

    仔细一看还有一个条件是边权小于10;

    所以拆点!把一个点拆成10个点表示到它不同的距离,那么和它相连的那些点就可以跟某个距离的点连边权为1的边;

    虽然没有自己想出来,不过1A还是极好的!(因为太简单了)

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int n,T,w[15][15],tot,id[15][15],mod=2009;
    struct Matrix{
        int a[105][105];
        Matrix(){memset(a,0,sizeof a);}
        Matrix operator * (const Matrix &y) const
        {
            Matrix x;
            for(int i=1;i<=tot;i++)
                for(int k=1;k<=tot;k++)
                    for(int j=1;j<=tot;j++)
                        (x.a[i][j]+=a[i][k]*y.a[k][j])%=mod;
            return x;
        }
        void init(){for(int i=1;i<=tot;i++)a[i][i]=1;}
    }f,ans;
    Matrix pw(Matrix x,int k)
    {
        Matrix ret; ret.init();
        for(;k;k>>=1,x=x*x)
            if(k&1)ret=ret*x;
        return ret;
    }
    int main()
    {
        scanf("%d%d",&n,&T);
        char ch[15];
        for(int i=0;i<n;i++)
        {
            scanf("%s",&ch);
            for(int j=0;j<n;j++)
                w[i][j]=ch[j]-'0';
        }
        for(int i=0;i<n;i++)
            for(int j=0;j<=9;j++)
            {
                id[i][j]=++tot;
                if(j)f.a[tot-1][tot]++;
            }
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                if(w[i][j])f.a[id[i][w[i][j]-1]][id[j][0]]++;
        ans.a[1][id[0][0]]=1;
        Matrix fn=pw(f,T);
        ans=ans*fn;
        printf("%d",ans.a[1][id[n-1][0]]);
        return 0;
    }
  • 相关阅读:
    绿色通用的网站后台系统管理模板
    本站源码免费下载-木庄网络博客
    expr 数字操作
    wget 实现web监控脚本
    wget 监控web服务器
    read + 计算
    判断字符串长度
    替换字符串
    shell 字符串操作
    shell 定义变量
  • 原文地址:https://www.cnblogs.com/Zinn/p/9254628.html
Copyright © 2020-2023  润新知