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

baoj1875 HH去散步 【矩阵转移】

时间:2015-03-30 11:27:08      阅读:161      评论:0      收藏:0      [点我收藏+]

标签:

Brief description :

给定一个可能重边但没有自环的无向图,要求计算 A, B 两点之间步数为 t 的方案数。答案模 45989。
(可以经过某个点某条边多次,但是不可以立即沿着同一条边折返。)
(.. N <= 20, M <= 60, t <= 2^30 ..)

Analyse :

由于“不会沿着同一条边折返”,因此从 A 点经过 k 步後的状态仅与最后一步所走的边和它的方向有关。
如果将每条无向边拆成两条有向边,那么仅于边有关。

用 i==(j^1),排除立即走回边。

比如: 2  0010(u1->v1)                                                    4  0100(u2->v2)

             3  0011(v1->u1)                                                    5  0101(v2->u2)

                    ---->   (2&1)==3  (3&1)==2                                 ----> (4&1)==5  (5&1)==4

友链:http://www.shuizilong.com/house/archives/sdoi-2009-hh%E5%8E%BB%E6%95%A3%E6%AD%A5/


CODE:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<string>
#include<queue>
#include<deque>
#include<stack>
#include<map>
#include<set>
#define INF 0x7fffffff
#define SUP 0x80000000
#define _p 45989
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;

typedef long long LL;
const int N=100007;

struct Edge{                 //邻接表节点
    int to,next;
}E[133];
int head[55];
int tot=2;

void add_(int u,int v)
{
    E[tot].to=v;
    E[tot].next=head[u];
    head[u]=tot++;
}

struct Matrix{
    int mat[133][133];
    Matrix()
    {
        mem(mat,0);
    }
    friend Matrix operator *(Matrix a,Matrix b)   //非成员函数重载
    {
        Matrix ans;
        for(int i=1;i<=tot;i++)
        {
            for(int j=1;j<=tot;j++)
            {
                for(int k=1;k<=tot;k++)
                    ans.mat[i][j]+=a.mat[i][k]*b.mat[k][j]%_p,ans.mat[i][j]%=_p;
            }

        }
        return ans;
    }

    friend Matrix operator^(Matrix a,int b)
    {
        Matrix ans;
        for(int i=1;i<=tot;i++) ans.mat[i][i]=1;
        while(b)
        {
            if(b&1) ans=ans*a;    //出去回边
            a=a*a;
            b>>=1;
        }
        return ans;
    }
};




int main()
{
    int n,m,t,a,b;
    while(scanf("%d%d%d%d%d",&n,&m,&t,&a,&b)==5)
    {
        mem(head,-1);
        int u,v;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&u,&v);
            add_(u,v);
            add_(v,u);
        }

        Matrix st,tt;
        for(int i=head[a];i!=-1;i=E[i].next) st.mat[1][i]=1;   //初始的一步

        vector<int> en;
        for(int i=2;i<tot;i++)    //转移的矩阵
        {
            int to=E[i].to;
            if(to==b) en.push_back(i);
            for(int j=head[to];j!=-1;j=E[j].next)  
            {
                if(i==(j^1)) continue;
                tt.mat[i][j]=1;
            }
        }

        int ans=0;
        st=st*(tt^(t-1));       // 1+(t-1)==t步  ,即初始一步+转移t-1次
        for(int i=0;i<en.size();i++)
        {
            ans=(ans+st.mat[1][en[i]])%_p;
        }
        printf("%d\n",ans);
    }


    return 0;
}



baoj1875 HH去散步 【矩阵转移】

标签:

原文地址:http://blog.csdn.net/code_or_code/article/details/44746657

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