Codeforces723E One-Way Reform【欧拉回路】
题意:给你n点m边的图,然后让你确定每条边的方向,使得入度=出度的点最多 。
度数为偶数的点均能满足入度 = 出度。
证明:度数为奇数的点有偶数个,奇度点两两配对连无向边,则新图存在欧拉回路,则可使新图所有点入度 = 出度。
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define X first 4 #define Y second 5 typedef long long ll; 6 const int N = 205; 7 int d[N], head[N], tot; 8 int to[N*N], nex[N*N], vis[N*N]; 9 vector< pair<int, int> > ans; 10 void init(){ 11 tot = 0; 12 memset(d, 0, sizeof(d)); 13 memset(head, -1, sizeof(head)); 14 ans.clear(); 15 } 16 void add(int u, int v, int w){// w = 0, exit; w = -1, add 17 d[v]++; 18 to[tot] = v; 19 nex[tot] = head[u]; 20 vis[tot] = w; 21 head[u] = tot++; 22 } 23 void dfs(int x){ 24 for(int& i = head[x]; ~i; ){ 25 if(vis[i] == 1) { 26 i = nex[i]; 27 continue ; 28 } 29 if(vis[i] == 0) ans.push_back( make_pair(x, to[i]) ); 30 vis[i] = vis[i^1] = 1; 31 dfs(to[i]); 32 } 33 } 34 35 int main(){ 36 int t; scanf("%d", &t); 37 while(t--){ 38 init(); 39 int n, m, u, v; 40 scanf("%d%d", &n, &m); 41 for(int i = 0; i < m; i++){ 42 scanf("%d%d", &u, &v); 43 add(u, v, 0); 44 add(v, u, 0); 45 } 46 vector<int> tmp; 47 int ret = n; 48 for(int i = 1; i <= n; i++) 49 if(d[i]&1) tmp.push_back(i), ret--; 50 for(int i = 0; i < tmp.size(); i += 2){ 51 add(tmp[i], tmp[i+1], -1); 52 add(tmp[i+1], tmp[i], -1); 53 } 54 for(int i = 1; i <= n; i++) 55 dfs(i); 56 printf("%d\n", ret); 57 for(int i = 0; i < ans.size(); i++) 58 printf("%d %d\n", ans[i].X, ans[i].Y); 59 } 60 return 0; 61 }
诸神对凡人心生艳羡,厌倦天堂。