CF209C Trails and Glades[欧拉回路]

欧拉回路的好题emm

题意:一张n个点,m条边的无向图,问你最少需要添加多少条边,能使得当前图存在欧拉回路

思路:我们根据欧拉回路的性质,肯定要先求出图中所有点的度数,若一个点是奇数入度,那么我们必定要凑成偶数,然后我们不难发现,把所有的点划分成联通块,一个连通块的包含奇度数点,那么他可以和另一个联通块内的奇度数点直接相连,花费为一条边,若不包含,则需要两条边来连接外界,所以我们可以得出两种情况

1.图中只有一个联通块,那么ans=(奇度数点个数)/2,

2.图中有多个联通块,若包含奇度数点,那么ans=(奇度数点个数)/2+偶度数联通块个数,没有奇度数点ans=偶度数联通块个数

代码

//By AcerMo
#include<cmath>
#include<queue> 
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define INF 0x7fffffff
using namespace std;
const int M=1000500;
int n,m;
bool vis[M];
int fa[M],deg[M],in[M];
inline int read()
{
	int x=0;char ch=getchar();
	while (ch>'9'||ch<'0') ch=getchar();
	while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return x; 
}
inline int find(int x)
{
	if (x!=fa[x]) return fa[x]=find(fa[x]);
	return x;
}
inline void unionn(int a,int b)
{
	int r1=find(a),r2=find(b);
	if (r1!=r2) fa[r2]=r1;
	return ;
}
inline void constt()
{
	for (int i=1;i<=n;i++)
	fa[i]=i,vis[i]=in[i]=deg[i]=0;
	return ;
}
int main()
{
	while (scanf("%d%d",&n,&m)!=EOF)
	{
		constt();vis[1]=1;
		for (int i=1;i<=m;i++)
		{
			int u=read(),v=read();
			if (u!=v) 
			{
				in[u]++,in[v]++;
				vis[u]=vis[v]=1;
				unionn(u,v);
			}
			else vis[u]=1;
		}
		for (int i=1;i<=n;i++)
			if (in[i]&1) 
				deg[find(i)]++;
		int ans=0,que=0,cnt=0;
		for (int i=1;i<=n;i++)
		if (vis[i]&&find(i)==i)
		{
			if (deg[i]) ans+=deg[i];
			else que++;
			cnt++;
		}	
		if (cnt==1) printf("%d\n",ans/2);
		else printf("%d\n",ans/2+que);			
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/acerandaker/article/details/80966150