如果栈底的边的两个结点都是奇数点:其实这个时候只有一种情况并且只会出现一次,就是这条边有一个点是起点。如果这个时候未跑的边数大于1,那么起点一定还有一个边 x 连接着偶数点,这个时候我们可以删除边 x 以此来改变起点的奇偶性。所以这个时候我们可以删除栈顶的边,也就是将奇数点转移。(为什么栈顶的边是可以的?因为最后一条边一定是连接到起点的,跑欧拉回路最终要回到起点的嘛。)这样我们最后只会剩下一条边。
Code
#include<iostream>#include<cstdio>usingnamespace std;intread(){
int x =0, f =1;char ch =getchar();while(ch <'0'|| ch >'9'){
if(ch =='-') f =-f; ch =getchar();}while(ch >='0'&& ch <='9'){
x = x *10+ ch -'0'; ch =getchar();}return x * f;}constint maxN =500005;int du[maxN];bool vis[maxN];int n, m;struct EDGE{
int adj, to, id;EDGE(int a =-1,int b =0,int c =0):adj(a),to(b),id(c){
}}edge[maxN <<1];int head[maxN], cnt;voidinit(){
cnt =0;for(int i =0; i <= n;++ i ){
head[i]=-1;
du[i]=0;}for(int i =0; i <= m;++ i ){
vis[i]=false;}}voidadd_edge(int u,int v,int id){
edge[cnt]=EDGE(head[u], v, id);
head[u]= cnt ++;}
pair<int,int>pi[maxN];int Stack[maxN], ans[maxN], top, tot;voiddfs(int u){
while(~head[u]){
int i = head[u];int v = edge[i].to;int id = edge[i].id;
head[u]= edge[i].adj;if(vis[id])continue;
vis[id]=true;dfs(v);
Stack[++top]= id;}}voidsolve(){
int l =1, r = top;while(l < r){
int u = pi[Stack[l]].first, v = pi[Stack[l]].second;if(du[u]&1&& du[v]&1){
ans[++ tot]= Stack[r];
u = pi[Stack[r]].first, v = pi[Stack[r]].second;-- r;}else{
ans[++ tot]= Stack[l];++ l;}-- du[u],-- du[v];}}intmain(){
n =read(), m =read();init();for(int i =1; i <= m;++ i ){
int u, v;
u =read(), v =read();add_edge(u, v, i);add_edge(v, u, i);
pi[i]=make_pair(u, v);++ du[u],++ du[v];}for(int i =1; i <= n;++ i ){
top =0;dfs(i);if(top){
solve();}}printf("%d\n", tot);for(int i =1; i <= tot;++ i ){
printf("%d%c", ans[i],(i == tot ?'\n':' '));}return0;}