码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2018-07-02 17:13:36      阅读:153      评论:0      收藏:0      [点我收藏+]

标签:names   tar   through   php   com   拆点   tps   ext   bzoj   

题目: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;
}

 

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

标签:names   tar   through   php   com   拆点   tps   ext   bzoj   

原文地址:https://www.cnblogs.com/Zinn/p/9254628.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!