题意
N个点M条边的图,问最少加几条边可以使其变成欧拉图。
2<=N<=1e5 1<=M<=2e5
题解
即使所有点均变为偶点。
全是偶点的连通块可以缩成一个单点。
增加一条边可以消除两个奇点。单点可以加入任意一条边中,即通过增加一条边消除。
答案为 奇点数/2+单点数。
注意两点一边的图也是欧拉图。(现场因为这个没过)
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int d[100010]; 5 vector<int > v[100010]; 6 bool h[100010], pd(0); 7 8 void DFS(int x) 9 { 10 h[x] = 1; 11 if (d[x] & 1) 12 pd = 1; 13 for (int i = 0; i < v[x].size(); ++i) 14 if (!h[v[x][i]]) 15 DFS(v[x][i]); 16 } 17 18 int main() 19 { 20 memset(d, 0, sizeof(d)); 21 memset(h, 0, sizeof(h)); 22 int n, m; 23 scanf("%d%d", &n, &m); 24 for (int i = 0; i < m; ++i) 25 { 26 int x, y; 27 scanf("%d%d", &x, &y); 28 v[x].push_back(y); 29 v[y].push_back(x); 30 d[x]++; 31 d[y]++; 32 } 33 if (n == 2) 34 { 35 printf("%d\n", 1 - m); 36 return 0; 37 } 38 int cnt(0); 39 for (int i = 1; i <= n; ++i) 40 if (!h[i]) 41 { 42 // printf("%d\n", i); 43 pd = 0; 44 DFS(i); 45 if (!pd) 46 cnt++; 47 } 48 int ji(0); 49 for (int i = 1; i <= n; ++i) 50 if (d[i] & 1) 51 ++ji; 52 // printf("%d %d\n", ji, cnt); 53 if ((!ji) && (cnt == 1)) 54 puts("0"); 55 else 56 printf("%d\n", ji / 2 + cnt); 57 58 return 0; 59 }