题目大意:
- 给定一个(n)个点(m)条边的无向图。
- 你可以在这张无向图上加任意多条无向边。
- 需要给所有的无向边定向,使得每一个的入度和出度都是偶数。
- 边可以是自环,也可以是重边。
题目链接:527E. Data Center Drama。
题解:考虑一个图能够这么定向的充要条件。就是一张图上,每一个点的度数是偶数并且边的总数是偶数。
这一道题我们发现一个很好的条件,就是可以连自环,并且自环不改变当前点度数的奇偶性。
那么直接把原图中度数为奇数的点两两连边,如果总边数变为奇数的话在连一个自环。
然后定向就直接一奇一偶一正一反就可以了。
代码:
#include <cstdio>
void read(int &a){
a=0;
char c=getchar();
while(c<'0'||c>'9'){
c=getchar();
}
while(c>='0'&&c<='9'){
a=(a<<1)+(a<<3)+(c^48);
c=getchar();
}
}
const int Maxn=100000;
const int Maxm=300000;
int num;
bool vis[Maxm<<1|5];
int head[Maxn+5],arrive[Maxm<<1|5],nxt[Maxm<<1|5],tot;
int deg[Maxn+5];
void add_edge(int from,int to){
arrive[++tot]=to;
nxt[tot]=head[from];
head[from]=tot;
}
int n,m;
int lis[Maxn+5],lis_len;
void dfs(int u){
for(int &i=head[u];i;i=nxt[i]){
if(vis[i]){
continue;
}
int v=arrive[i];
vis[i]=vis[((i-1)^1)+1]=1;
dfs(v);
num++;
if(num&1){
printf("%d %d
",u,v);
}
else{
printf("%d %d
",v,u);
}
}
}
int main(){
read(n),read(m);
int u,v;
for(int i=1;i<=m;i++){
read(u),read(v);
add_edge(u,v);
add_edge(v,u);
deg[u]++;
deg[v]++;
}
for(int i=1;i<=n;i++){
if(deg[i]&1){
lis[++lis_len]=i;
}
}
for(int i=1;i<=lis_len;i+=2){
add_edge(lis[i],lis[i+1]);
add_edge(lis[i+1],lis[i]);
m++;
}
if(m&1){
m++;
add_edge(1,1);
add_edge(1,1);
}
printf("%d
",m);
dfs(1);
return 0;
}