欧拉回路的好题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;
}