大意:
给你一个无向图。
要求加最少的边,然后给这些无向图的边定向,使得每一个点的出入度都是偶数。
输出定向后的边数和边集。
n<=10^5 m<=2*10^5
很巧妙的构造题……
可以发现答案的下界是\(度数为奇数的点个数m + 度数为奇数的点个数/2\)
因为是无向图,度数为奇数的点不可能有奇数个,于是考虑往每两个度数为奇数的点间连一条边。于是就可以愉快地跑欧拉回路啦。跑出来后在欧拉回路上构造像\(a\rightarrow b\leftarrow c\rightarrow d ……y\rightarrow x\leftarrow a\)这样的路径就行了,相当于把每个点的度数平分。
那如果构造出来的欧拉回路是类似于\(a- b- c- a\)这样,只有奇数条边,怎么分都分不好怎么办?起点和终点加个自环就OK了。
代码:
#include <bits/stdc++.h>
#define N 100005
using namespace std;
void rd(int &x){
int y=0;char c=getchar();
while(c<'0' || c>'9') c=getchar();
while(c>='0' && c<='9') y=y*10+c-'0',c=getchar();
x=y;
}
struct ed{
int v,nxt;
bool f;
}e[N<<3];
int head[N],cnt=1,deg[N],p[1000005],tot=0;
bool vis[N];
void add(int u,int v){
e[++cnt]=(ed){v,head[u],0},head[u]=cnt;
e[++cnt]=(ed){u,head[v],0},head[v]=cnt;
}
void dfs(int u){
for(int &i=head[u];i;i=e[i].nxt){
int to=e[i].v;
if(!e[i].f){
e[i].f=1;
e[i^1].f=1;
dfs(to);
}
}
p[++tot]=u;
}
int main(){
int n,m,a,b,ans=0,lst=0,qwq=0,i;
rd(n),rd(m);
for(i=1;i<=m;++i){
rd(a),rd(b);
add(a,b);
deg[a]++,deg[b]++;
}
for(i=1;i<=n;++i){
if(deg[i]&1){
ans++;
if(ans%2==1) lst=i;
else if(lst) add(lst,i);
}
}
m+=ans/2;
if(m&1) add(1,1),m++;
printf("%d\n",m);
for(i=1;i<=n;++i){
if(!vis[i]){
tot=qwq=0;
dfs(i);
for(i=1;i<tot;++i) printf("%d %d\n",p[i+qwq],p[i+(!qwq)]),qwq^=1;
}
}
}