传送门:Ant Trip
题意大概是给定一个图,求出它最少需由几笔画成。若给出的图是欧拉图,那么可由一笔画成;而若给出的是半欧拉图,那么就需要计算奇度顶点的个数(由结论“非(半)欧拉图画成的笔数为该图中奇度顶点数目/2”)。
#include <bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1e5+5;
int n, m;
int deg[maxn], oddNum[maxn];
int pre[maxn], vis[maxn];
void init()
{
for(int i = 0; i < maxn; ++i)
{
deg[i] = oddNum[i] = vis[i] = 0;
pre[i] = i;
}
}
int Find(int x)
{
int r = x;
while(pre[r] != r) //寻根
r = pre[r];
int i = x, j;
while(i != r) //路径压缩,由多级分层压缩至单级
{
j = pre[i];
pre[i] = r;
i = j;
}
return r;
}
void Union(int x, int y)
{
int rx = Find(x), ry = Find(y);
if(rx != ry)
pre[rx] = pre[ry];
}
void read()
{
int u, v;
for(int i = 0; i < m; ++i)
{
cin >> u >> v;
++deg[u];
++deg[v];
Union(u, v);
}
}
void solve()
{
int rt = 0;
for(int i = 1; i <= n; ++i)
{
rt = Find(i);
if(deg[i])
vis[rt] = 1;
if(deg[i]%2)
++oddNum[rt];
}
int ans = 0;
for(int i = 1; i <= n; ++i)
if(vis[i])
{
if(!oddNum[i])
++ans;
else
ans += oddNum[i]/2;
}
cout << ans << "\n";
}
int main()
{
//freopen("in.txt", "r", stdin);
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
while(cin >> n >> m)
{
init();
read();
solve();
}
return 0;
}