太鼓达人:欧拉回路(暴搜)
一上来这个专题就死磕了这道题一上午,然后发现
类似二分图?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; }
Keep it simple and stupid.