题目链接:http://codeforces.com/problemset/problem/723/E
-----------------------------------------------------------------------
首先可以想一想给定一个图 如果不要求输出方案的话答案是多少
由于初始度数为奇数的点无论怎样 最后也不可能修改成入度 = 出度的
因此答案一定不超过初始度数为偶数的点的个数
再考虑这些初始度数为奇数的点 由于是无向图 这样的点的个数显然是偶数个的
我们如果对这些点每两个分为一组 组内连一条无向边
显然对于每个联通块 都可以找到一条欧拉回路 而欧拉回路中所有点的入度 = 出度
也就是说这样修改后所有点都是合法的了 如果再把之前添加了的边去掉
那么初始度数为偶数的点不受影响 初始度数为奇数的点全部变为不合法点
因此对于任意一个图 都可以构造出一个答案等于初始度数为偶数的点的个数的方案
于是这题接下来只需要会用求欧拉回路的方法就可以解决了
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 210, E = N * N << 1; 4 int firste[N], nexte[E], v[E], d[N]; 5 bool used[N], mp[N][N], color[E]; 6 int e; 7 void build(int x, int y, int z = 1) 8 { 9 nexte[++e] = firste[x]; 10 firste[x] = e; 11 v[e] = y; 12 color[e] = 0; 13 if(z) 14 ++d[x]; 15 } 16 int sta[N], route[E]; 17 int t, n, m, top, len; 18 void dfs(int u) 19 { 20 used[u] = 1; 21 for(int p = firste[u]; p; p = nexte[p]) 22 if(!color[p]) 23 { 24 color[p] = color[p ^ 1] = 1; 25 dfs(v[p]); 26 } 27 route[len++] = u; 28 } 29 int main() 30 { 31 scanf("%d", &t); 32 while(t--) 33 { 34 memset(firste, 0, sizeof firste); 35 memset(d, 0, sizeof d); 36 memset(used, 0, sizeof used); 37 memset(mp, 0, sizeof mp); 38 e = 1; 39 scanf("%d%d", &n, &m); 40 int x, y; 41 for(int i = 1; i <= m; ++i) 42 { 43 scanf("%d%d", &x, &y); 44 build(x, y); 45 build(y, x); 46 mp[x][y] = mp[y][x] = 1; 47 } 48 top = 0; 49 int ans = n; 50 for(int i = 1; i <= n; ++i) 51 if(d[i] & 1) 52 { 53 --ans; 54 if(top & 1) 55 { 56 build(i, sta[top - 1], 0); 57 build(sta[top - 1], i, 0); 58 } 59 sta[top++] = i; 60 } 61 len = 0; 62 for(int i = 1; i <= n; ++i) 63 if(!used[i]) 64 dfs(i); 65 printf("%d\n", ans); 66 for(int i = 0; i < len; ++i) 67 if(mp[route[i]][route[(i + 1) % len]]) 68 { 69 mp[route[i]][route[(i + 1) % len]] = mp[route[(i + 1) % len]][route[i]] = 0; 70 printf("%d %d\n", route[i], route[(i + 1) % len]); 71 } 72 } 73 return 0; 74 }