欧拉回路(HDU 1878)

题目链接

题目描述

欧拉回路是指不令笔离开纸面,可画过图中每条边仅一次,且可以回到起点的一条回路。现给定一个图,问是否存在欧拉回路?

输入格式

测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是节点数N ( 1 < N < 1000 )和边数M;随后的M行对应M条边,每行给出一对正整数,分别是该条边直接连通的两个节点的编号(节点从1到N编号)。当N为0时输入结
束。

输出格式

每个测试用例的输出占一行,若欧拉回路存在则输出1,否则输出0。

输入样例

3 3
1 2
1 3
2 3
3 2
1 2
2 3
0

输出样例

1
0

欧拉通路/回路的判定

有向图

  • 欧拉通路:图是连通的,图中只有两个奇度点,分别是欧拉通路的两个端点。对于欧拉通路,除起点、终点外,每个点如果进入,显然一定要出去,因此都是偶点。
  • 欧拉回路:图是连通的,点均为偶度点。对于欧拉回路,每个点进入、出去的次数相等,因此没有奇点。

无向图

  • 欧拉通路:图是连通的,除两顶点外其余点的入度等于出度,且这两个顶点中,一个顶点入度比出度大1(起点),另一个入度比出度小1(终点)
  • 欧拉回路:图是连通的,图中所有点的入度等于出度。

思路

对于判定欧拉通路/回路是否存在的问题,显然我们只需判断两点:

  1. 图是否联通。
  2. 顶点度数的统计与判断。

对于第一点,我们可以用并查集来统计连通分量/强连通分量的个数。如果个数为1,则转至第二点。否则,不存在欧拉通路/回路。
对于第二点,我们只需统计结束后做一个简单判断。

源程序

#include <bits/stdc++.h>
#define MAXN 1005
using namespace std;
int n,m,degree[MAXN],father[MAXN];
int read()	//快读 
{
	int sum=0;
	char c=getchar();
	while(c<'0'||c>'9')c=getchar();
	while(c>='0'&&c<='9'){
		sum=sum*10+c-'0';
		c=getchar();
	}
	return sum;
}
int find(int x)	//并查集 
{
	if(x==father[x])return x;
	return father[x]=find(father[x]); //路径压缩 
}
void Union(int x,int y)	//合并
{
	x=find(x);
	y=find(y);
	if(x!=y)father[x]=y;
	return ;
} 
int main()
{
	while(1){
		n=read();
		if(n==0)break;
		m=read();
		for(int i=1;i<=n;i++){	//初始化 
			degree[i]=0;
			father[i]=i;
		}
		for(int i=1;i<=m;i++){	//统计顶点度数并建立并查集 
			int x=read(),y=read();
			degree[x]++;
			degree[y]++;
			Union(x,y);
		}
		int cnt=0;	//记录连通分量个数 
		for(int i=1;i<=n;i++) 
			if(i==father[i])
				cnt++;
		if(cnt!=1)cout<<0<<endl;
		else{
			int num=0;	//记录奇度点个数
			for(int i=1;i<=n;i++)
				if(degree[i]&1)num++;
			if(num==0)cout<<1<<endl;	//不存在奇度点
			else cout<<0<<endl;		
		}
	} 
	return 0;
} 
发布了19 篇原创文章 · 获赞 0 · 访问量 139

猜你喜欢

转载自blog.csdn.net/weixin_43960284/article/details/105149259
今日推荐