这题说的是给了n个点 和m条边, 这m条边是无向的,任务是将这些边变成有向的,并且添加最少的有向边使得这个图中每个点的入度为偶数, 出度为偶数。
我们可以考虑使用欧拉回路来解决这个问题,这样说,假如一个图如果满足欧拉回路,那么 a b c d a , a - > b <-c ->d <-a 只要这样一下就解决了问题。我们知道要使得这个图是欧拉回路,必须满足每个点的度数为偶数 我们将度数为奇数的点, 两两一对 形成一条边。然后跑一个欧拉回路,接着像上面举得例子一样 同时给一个点增加两个出度或者增加两个入度, 但是可能会有问题存在就是起始点 我们可以知道当边为奇数的时候,起点的入度和出度为奇数,我们在给他俩一个自环就解决了。
1 #include <iostream> 2 #include <algorithm> 3 #include <string.h> 4 #include <cstdio> 5 using namespace std; 6 const int maxn=100000+10; 7 const int M =500000+10; 8 int G[maxn],next[M*2],num,To[M*2],d[maxn],a[maxn],nn; 9 bool use[M*2]; 10 struct Edge{ int form,to ;}top[M]; 11 void add_edg(int x, int y){ 12 num++; 13 next[M+num] = G[x]; 14 G[x]=M+num; To[M+num] = y; 15 next[M-num] = G[y]; 16 G[y] = M-num; To[M-num] =x; 17 } 18 void dfs(int u){ 19 20 while(G[u]){ 21 if(!use[G[u]]){ 22 use[G[u]] = use[M*2-G[u]] = true; 23 int to = To[G[u]]; 24 dfs(To[ G[u] ]); 25 top[nn++]=(Edge){u,to}; 26 } 27 G[u]=next[ G[u] ]; 28 } 29 } 30 int main() 31 { 32 int n,m; 33 while(scanf("%d%d",&n,&m)==2){ 34 memset(d,0,sizeof(d)); 35 memset(G,0,sizeof(G)); 36 memset(use,false,sizeof(use)); 37 num=nn=0; 38 for(int i=0; i<m; i++){ 39 int a,b; 40 scanf("%d%d",&a,&b); 41 d[a]++; d[b]++; 42 add_edg(a,b); 43 } 44 int un = 0; 45 for(int i=1; i<=n; i++ ) 46 if(d[i]&1){ 47 a[un++]=i; 48 } 49 int cound=m; 50 for(int i =0; i<un; i+=2){ 51 add_edg(a[i],a[i+1]);cound++; 52 } 53 if(cound&1)cound++; 54 printf("%d\n",cound); 55 dfs(1); 56 for(int i =0; i<nn; i++) 57 if(i&1) printf("%d %d\n",top[i].form,top[i].to); 58 else printf("%d %d\n",top[i].to,top[i].form); 59 if( (nn&1) ) printf("1 1\n"); 60 } 61 return 0; 62 }