baoj1875 HH去散步 【矩阵转移】

来源:互联网 发布:c语言 fft 编辑:程序博客网 时间:2024/05/17 06:49

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;}



0 0
原创粉丝点击