题意:
给一个无向图..问由最少可以分解成多少个欧拉(通/回)路
题解:
我是觉得首先要找出每一个联通块..在一个联通块中..两个奇数度的点可以构一条通路...虽然不知道怎么证明..感觉上在一个联通块上最少需要的一笔画为其max(1,其奇数度点数/2)...1是因为若此联通块没有奇数度点..也要画一条欧拉回路把该联通块所有边覆盖...
直觉还是挺正确的..也是多画了几个图观察出来的..但是有个trick...有些点是独立的..没有边..处理的时候注意.就无视这些点..而不要把这些点也看成联通块了...
Program:
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<time.h>
#include<map>
#include<algorithm>
#define ll long long
#define eps 1e-5
#define oo 1000000007
#define pi acos(-1.0)
#define MAXN 100005
#define MAXM 500005
using namespace std;
int d[MAXN],father[MAXN],F[MAXN],T[MAXN];
bool used[MAXN];
int getfather(int x)
{
if (father[x]==x) return x;
return father[x]=getfather(father[x]);
}
int main()
{
int n,m,i,x,y,ans;
while (~scanf("%d%d",&n,&m))
{
memset(d,0,sizeof(d));
memset(used,false,sizeof(used));
for (i=1;i<=n;i++) father[i]=i;
while (m--)
{
scanf("%d%d",&x,&y);
d[x]++,d[y]++;
used[x]=used[y]=true;
father[getfather(x)]=getfather(y);
}
memset(F,0,sizeof(F)),m=0;
for (i=1;i<=n;i++)
if (used[i])
{
if (!F[getfather(i)]) F[father[i]]=++m,T[m]=0;
if (d[i]%2) T[F[father[i]]]++;
}
ans=0;
for (i=1;i<=m;i++) ans+=max(1,T[i]/2);
printf("%d\n",ans);
}
return 0;
}