传送门
经过一番思索可发现如果要存在一种合法方案,图必须可以被划分成两个部分:
G
1
G_1
G1和
G
2
G_2
G2。其中
G
1
G_1
G1要求具有一条欧拉路径或欧拉回路,并且在欧拉路径(回路)的终点
t
t
t处有一个以
t
t
t为中心的菊花图
G
2
G_2
G2,
G
1
G_1
G1和
G
2
G_2
G2共同构成
G
G
G。
关键是如何找到
G
1
G_1
G1和
G
2
G_2
G2。考虑枚举
t
t
t,对于每个
t
t
t我们先考虑那些非临接点中有几个点的度数是奇数:
若有两个及以上,那么显然
t
t
t是不能作为
G
2
G_2
G2的菊花图中心点;
若有一个,那么显然
G
1
G_1
G1的欧拉路径必须以那唯一一个奇度数的非临接点
s
s
s为起点,
t
t
t为终点,自然所有奇度数的临接点与
t
t
t相连的边都得放到
G
2
G_2
G2,我们先将这些边删除,然后跑一遍欧拉路径,最后统计看
G
1
+
G
2
G_1+G_2
G1+G2是否等于
G
G
G即可;
若有零个,那么欧拉路径的起点只能在
t
t
t的临接点找,并且还必须得是奇度数,不妨枚举这些奇度数的临接点
s
s
s,除了
s
s
s以外的奇度数的点与
t
t
t相连的边都得划分到
G
2
G_2
G2中,还是像上一种情况一样
c
h
e
c
k
check
check一下看是否
G
1
G_1
G1连通,然后
G
1
+
G
2
G_1+G_2
G1+G2是否等于
G
G
G。如果没有奇度数的临接点的话,那么整个图显然存在一个从
t
t
t到
t
t
t的欧拉路径。
虽然讲起来简单,但是代码还是不太好写,具体细节见代码。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 6005;
int h[maxn],ee=0,vs[maxn],n,m,deg[maxn],near[maxn];
struct EDGE{
int u,v;
}edge[maxn];
struct Edge{
int v,next;
}e[maxn];
void init(int n){
memset(h,-1,sizeof(int)*(n+2));
memset(deg,0,sizeof(int)*(n+2));
ee=0;
}
void addedge(EDGE &edge){
int u=edge.u,v=edge.v;
deg[u]++;
deg[v]++;
e[ee]=Edge{v,h[u]};
h[u]=ee++;
e[ee]=Edge{u,h[v]};
h[v]=ee++;
}
vector<int>ans1;
vector<int>ans2;
void dfs(int u){
while(~h[u]){
int i=h[u];
int v=e[i].v;
h[u]=e[h[u]].next;
if(vs[i])continue;
vs[i]=vs[i^1]=1;
deg[u]--,deg[v]--;
dfs(v);
ans1.push_back(v);
}
}
bool work(int u){
memset(near,0,sizeof(int)*(n+2));
memset(vs,0,sizeof(int)*(2*m+4));
for(int i=h[u];~i;i=e[i].next){
int v=e[i].v;
near[v]=1;
}
int ct=0,s=0;
for(int i=1;i<=n;++i){
if(!near[i] && i!=u){
if(deg[i]&1){
ct++;
s=i;
}
}
}
if(ct>=2)return false;
if(ct==1){
for(int i=h[u];~i;i=e[i].next){
int v=e[i].v;
if(deg[v]&1){
vs[i]=vs[i^1]=1;
deg[v]--,deg[u]--;
ans2.push_back(v);
ans2.push_back(u);
}
}
dfs(s);
ans1.push_back(s);
reverse(ans1.begin(),ans1.end());
for(int i=1;i<=n;++i)if(deg[i])return false;
return true;
}else{
s=0;
vector<EDGE>g;
for(int i=h[u];~i;i=e[i].next){
int v=e[i].v;
if(deg[v]&1)g.push_back(EDGE{i,e[i].v}),vs[i]=vs[i^1]=1,deg[u]--,deg[v]--;
}
for(auto d:g){
s=d.v;int i=d.u;
vs[i]=vs[i^1]=0;
deg[u]++,deg[s]++;
ans1.clear();
dfs(s);
ans1.push_back(s);
bool ok=true;
for(int i=1;i<=n;++i)if(deg[i]){
ok=false;
break;
}
if(ok){
reverse(ans1.begin(),ans1.end());
for(auto dd:g){
if(dd.v!=s){
ans2.push_back(dd.v);
ans2.push_back(u);
}
}
return true;
}
memset(vs,0,sizeof(int)*(2*m+4));
init(n);
for(int i=1;i<=m;++i)addedge(edge[i]);
for(auto dd:g)vs[dd.u]=vs[dd.u^1]=1,deg[u]--,deg[dd.v]--;
}
for(int i=h[u];~i;i=e[i].next){
int v=e[i].v;
if(deg[v]&1){
ans2.push_back(v);
ans2.push_back(u);
}
}
if(!(deg[u]&1))dfs(u);else return false;
ans1.push_back(u);
for(int i=1;i<=n;++i)if(deg[i])return false;
return true;
}
return false;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i)scanf("%d%d",&edge[i].u,&edge[i].v);
for(int i=1;i<=n;++i){
init(n);
for(int j=1;j<=m;++j)addedge(edge[j]);
if(work(i)){
if(ans2.empty())printf("%d\n",(int)ans1.size());
else printf("%d\n",(int)ans1.size()+1+(int)ans2.size());
for(auto u:ans1){
printf("%d ",u);
}
if(!ans2.empty())printf("-1 ");
for(auto u:ans2)printf("%d ",u);puts("");
return 0;
}
}
printf("0\n");
}