题意
给定一张无向图,将每条边变成有向边,使得出度等于入度的点最多。输出最终入度=出度点的个数和每条有向边。
分析
第一问统计度数为偶数的点即可。
联想欧拉回路上的每个点出度=入度,但原图并不一定是无向图的欧拉回路,可以补成欧拉回路,输出的时候不输出补的边。
考虑到一张图的奇数度数的点有偶数个,把它们分成2个点一组,然后每组加边,那么原图就有欧拉回路了。
代码
#include <cstdio> #include <cstring> #include <vector> #include <queue> #include <map> #include <cmath> #include <iostream> #include <algorithm> #define MAX 207 #define MAXN 10007 #define MAXM 50007 #define MOD 1000000007 using namespace std; typedef long long LL; struct Edge{ int from; int to; int next; }edge[MAXM*2]; int head[MAXN],tot,n,m,degree[MAXN]; int ans[MAXM*2],ansi,visit[MAXM*2],flag[MAXM*2]; void addEdge(int u, int v){ edge[tot].from=u; edge[tot].to=v; edge[tot].next=head[u]; head[u]=tot++; } void init(){ tot=ansi=0; memset(head,-1,sizeof head); memset(visit,0,sizeof visit); memset(degree,0,sizeof degree); memset(flag,0,sizeof flag); } void dfs(int now){ for(int k=head[now];k!=-1;k=edge[k].next){ if(!visit[k]){ visit[k]=visit[k^1]=1; dfs(edge[k].to); ans[ansi++]=k^1; } } } int cas,u,v; int main(){ scanf("%d",&cas); while(cas--){ scanf("%d%d",&n,&m); init(); for(int i=0;i<m;i++){ scanf("%d%d",&u,&v); degree[u]++; degree[v]++; addEdge(u,v); addEdge(v,u); } int ans1=0; int js[MAXN],jsi=0; for(int i=1;i<=n;i++){ if((degree[i]&1)==0){ ans1++; } else{ js[jsi++]=i; } } for(int i=0;i<jsi;i+=2){ //printf("add:%d %d\n",js[i],js[i+1]); addEdge(js[i],js[i+1]); addEdge(js[i+1],js[i]); } printf("%d\n",ans1); for(int i=1;i<=n;i++){ dfs(i); } for(int i=0;i<ansi;i++){ int d=ans[i]; if(d<m*2) printf("%d %d\n", edge[d].from,edge[d].to); } } return 0; }