zoukankan      html  css  js  c++  java
  • bzoj1297: [SCOI2009]迷路(矩阵乘法+拆点)

    1297: [SCOI2009]迷路

    题目:传送门 


    题解:

       又是一次涨姿势

       看完题目之后觉得很像DP,然后再看见T辣么大,第一个念头就是矩乘。。。

       然后就不会做了....膜一发肉大佬

       肥肠神奇,对于一个边权全都为1的邻接矩阵,直接做T次矩乘就是答案,因为1也可以当做是到该点的路径数嘛

       那么这题边权并不唯一,所以要拆点,而拆点的方式和之前的一道网路流的题目很像:

       因为边权是1~9的,我们直接就拆成十个点,然后拆的第i个点向第i-1个点连边(倒过来),流量就为1

       对于原本两个相连的点x、y,那么就将x的第1个点和y的第i个点连,i为原本的边权

       这样纸边权又全部为1啦,然后很开心的去矩乘啦啦啦~~

        


    代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<cmath>
     5 #include<algorithm>
     6 #define mod 2009
     7 using namespace std;
     8 struct node
     9 {
    10     int m[150][150];
    11     node(){memset(m,0,sizeof(m));}
    12 }A,B,C,pre;
    13 int n,T;char st[20];
    14 node multi(node a,node b)
    15 {
    16     node c;
    17     for(int i=1;i<=n*10;i++)    
    18         for(int j=1;j<=n*10;j++)
    19             for(int k=1;k<=n*10;k++)
    20                 c.m[i][j]=(c.m[i][j]+a.m[i][k]*b.m[k][j]%mod)%mod;
    21     return c;        
    22 }
    23 node p_m(node a,int b)
    24 {
    25     node ans;
    26     for(int i=1;i<=10;i++)ans.m[i][i]=1;
    27     while(b)
    28     {
    29         if(b%2==1)ans=multi(ans,a);
    30         a=multi(a,a);b/=2;
    31     }
    32     return ans;
    33 }
    34 int main()
    35 {
    36     scanf("%d%d",&n,&T);
    37     for(int i=1;i<=n;i++)for(int j=2;j<=10;j++)pre.m[(i-1)*10+j][(i-1)*10+j-1]=1;
    38     for(int i=1;i<=n;i++)
    39     {
    40         scanf("%s",st+1);
    41         for(int j=1;j<=n;j++)if(st[j]!='0')pre.m[(i-1)*10+1][(j-1)*10+st[j]-'0']=1;
    42     }
    43     node ans=p_m(pre,T);
    44     printf("%d
    ",ans.m[1][(n-1)*10+1]);
    45     return 0;
    46 }
  • 相关阅读:
    实验0 了解和熟悉操作系统
    学习进度条
    0302软件构建与教学
    评论任务
    学习进度条
    sprint3个人总结
    软件工程学期总结
    6.3 学术诚信与职业道德
    阅读《构建之法》第8、9、10章
    nodejs学习心得
  • 原文地址:https://www.cnblogs.com/CHerish_OI/p/8661829.html
Copyright © 2011-2022 走看看