太鼓达人:欧拉回路(暴搜)

Posted hzoi2018-xuefeng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了太鼓达人:欧拉回路(暴搜)相关的知识,希望对你有一定的参考价值。

技术图片

一上来这个专题就死磕了这道题一上午,然后发现

类似二分图?2h 样例都过不去

类似状压?1h 过样例了,WA 0

类似暴搜?10min AC

然而正解是欧拉回路

欧拉回路:

如果图G中的一个路径包括每个边恰好一次,则该路径称为欧拉路径(Euler path)。如果一个回路是欧拉路径,则称为欧拉回路(Euler circuit)。具有欧拉回路的图称为欧拉图

判断条件:

以下判断基于此图的基图连通。
无向图存在欧拉回路的充要条件
一个无向图存在欧拉回路,当且仅当该图所有顶点度数都为偶数,且该图是连通图。
有向图存在欧拉回路的充要条件
一个有向图存在欧拉回路,所有顶点的入度等于出度且该图是连通图。

前k个一定是0,确定好初态后,每次转移只会出现两种情况:0或1

因此dfs即可

注意在末态判断是要和初态完美契合

Code

技术图片
#include<cstdio>
#include<vector>
int ak,k,a[5000],ans[5000],num,rnum,full[15],pow[15],q[5000];
void bfs(int la,int tot)
    if(ak)return;
    if(tot==pow[k])
        if(ak)return;
        bool ok=1;
        //for(int i=1;i<=num;++i)printf("%d",ans[i]);puts("");
        for(int i=1;i<=k-1;++i)
            int up=((la<<i)&full[k]);
            if(a[up])ok=0;break;
            else q[++q[0]]=up,a[up]=1;
        
        for(int i=1;i<=q[0];++i)a[q[i]]=0;q[0]=0;
        if(!ok)return;
        while(num)if(!ans[num])num--,rnum++;else break;
        for(int i=1;i<=rnum;++i)putchar(0);
        for(int i=1;i<=num;++i)printf("%d",ans[i]);puts("");
        ak=1;
    
    la<<=1;
    if(!a[la])
        a[la]=1;
        ans[++num]=0;
        bfs(la&full[k-1],tot+1);
        a[la]=0;
        --num;
    
    if(!a[la|1])
        a[la|1]=1;
        ans[++num]=1;
        bfs((la|1)&full[k-1],tot+1);
        a[la|1]=0;
        --num;
    

int main()
    scanf("%d",&k);
    for(int i=0;i<=k;++i)full[i]=(1<<i)-1;
    for(int i=0;i<=k;++i)pow[i]=(1<<i);
    rnum=k;
    printf("%d ",pow[k]);
    a[0]=1;bfs(0,k);
    return 0;

 

以上是关于太鼓达人:欧拉回路(暴搜)的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ-3033太鼓达人 欧拉图 + 暴搜

bzoj3033: 太鼓达人 欧拉路径

bzoj3033 太鼓达人——欧拉图搜索

太鼓达人

bzoj3033太鼓达人 DFS欧拉图

欧拉回路的判断