bzoj 3033 太鼓达人——欧拉图搜索

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3033

思路:肯定是把2^m个数当成点,每个点连了2条入边、2条出边,然后求一个经过所有点一次的路径。

   但是这怎么做?又不是欧拉路的定义。

   肯定是把点变成边,于是一条边会连4条边,就用点把它们粘起来就能求个欧拉路了。

   然后觉得这不是个欧拉图吧? >o-o< 了以后,把右边的两条边转一转连一连,好像得出每个点连5条边的结论?(3条边)

   怎么办?TJ:https://blog.csdn.net/Clove_unique/article/details/70160122

原来是这样啊。分析一下点和边的含义,以点为中心分析它的度数。得出:这就是个欧拉图。

然后怎么求欧拉路?

竟然是暴搜。

有一些细节。比如dfs什么时候到终点之类的。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=(1<<10)+5,M=(1<<11)+5;
int m,lm,mod;
bool vis[M],flag,ans[M];
void dfs(int nw,int k)//在第k位 
{
    if(k==m+lm){flag=1;return;}
    if(k<=lm)
        for(int i=0;i<=1;i++)
        {
            int s=((nw<<1)|i);
            if(vis[s])continue; ans[k]=i;
            vis[s]=1; dfs(s&mod,k+1);
            if(flag)return; vis[s]=0;
        }
    else{
        int s=((nw<<1)|ans[k-lm]);
        if(vis[s])return;vis[s]=1;
        dfs(s&mod,k+1);
        if(flag)return; vis[s]=0;
    }
}
int main()
{
    scanf("%d",&m);mod=(1<<(m-1));lm=(mod<<1);mod--;
    printf("%d ",lm);
    for(int s=0;s<lm;s++)
    {
        dfs(s,m);if(flag)break;
    }
    for(int i=1;i<=lm;i++)printf("%d",ans[i]);
    return 0;
}
原文地址:https://www.cnblogs.com/Narh/p/9283081.html