Aiiage Camp Day3 I Interpreter

题意

  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 }

 

posted @ 2018-02-11 17:18  Aseer  阅读(117)  评论(0编辑  收藏  举报