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

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

类似二分图?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;
}

 

posted @ 2019-07-12 12:11  _xuefeng  阅读(177)  评论(0编辑  收藏  举报