题意:给一个无向图,N个顶点和M条边,问至少需要几笔才能把所有边画一遍
思路:只要知道一个结论就随便做了。
如果该连通分量是一个孤立的点,显然只需要0笔.
如果该连通分量是一个欧拉图或半欧拉图,只需要1笔.
非(半)欧拉图需要的笔数==该图中奇数度的点数目/2
对于每个以i为根的连通分量我们记录属于该连通分量的点数目num[i]和该连通分量中奇度点的个数odd[i],然后瞎搞就好了
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <set>
#include <ctime>
#include <cmath>
#include <cctype>
using namespace std;
#define maxn 100000+100
#define LL long long
int cas=1,T;
int pre[maxn];
int Find(int x)
{
return pre[x]==-1?x:pre[x]=Find(pre[x]);
}
int n,m;
int num[maxn];
int odd[maxn];
int degree[maxn];
int main()
{
while (scanf("%d%d",&n,&m)!=EOF)
{
memset(pre,-1,sizeof(pre));
memset(num,0,sizeof(num));
memset(odd,0,sizeof(odd));
memset(degree,0,sizeof(degree));
for (int i = 0;i<m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
degree[u]++;
degree[v]++;
u = Find(u);
v = Find(v);
if (u!=v)
pre[u]=v;
}
for (int i = 1;i<=n;i++)
{
num[Find(i)]++;
if (degree[i]%2)
odd[Find(i)]++;
}
int ans = 0;
for (int i = 1;i<=n;i++)
{
if (num[i]<=1)
continue;
else if (odd[i]==0)
ans++;
else if (odd[i]>0)
ans+=odd[i]/2;
}
printf("%d\n",ans);
}
//freopen("in","r",stdin);
//scanf("%d",&T);
//printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC);
return 0;
}