题目: 牛客网链接
概述: 欧拉回路是指不令笔离开纸面,可画过图中每条边仅一次,且可以回到起点的一条回路。现给定一个图,问是否存在欧拉回路?
思路: 确定无向图欧拉回路的充要条件:除孤立节点外,其它节点满足 1.连通 2.度为偶数。这里采用并查集进行操作,具体思路写在注释里。
采用scanf可以提高输入效率,大幅度提高。很多学校的oj要求的是连续输入很多组数据,之前因为忘记使用EOF导致运行超时,所以这一点一定要记住。
另外并查集自己简单总结一下几个步骤,方便以后做连通图相关的问题。
- 初步设置father数组:先给每个节点的father数组的相对应位置设置初始值。例如father[x] = x。这样做是为了防止孤立节点的问题。
- 再设置father数组:这次根据给出的路径,把相连的点union起来
- 看是不是都连在一起(除了孤立节点):就找一个度大于1的作为起始点,找他的father,然后后面找所有的非孤立节点的father应该都是一样的。
#include <iostream>
#include <memory.h>
using namespace std;
int father[1005], cnt[1005];
int find(int x) {
while (x != father[x])
{x = father[x];}
return x;
}
void union_find(int x, int y)
{
x = find(x);
y = find(y);
if(x != y) father[x] = y;
}
int main()
{
int N, M; //N对应着N个节点,M对应着M条边
while(scanf("%d", &N) != EOF && N)
{
scanf("%d", &M);
fill(father, father + 1005, 0);
//先把每个点的父节点设置成自己,保障孤立节点
for(int i = 1; i <= N; i++) father[i] = i;
//输入联通的两个节点
for(int i = 1; i <= M; i++)
{
int x, y;
scanf("%d", &x);
scanf("%d", &y);
cnt[x]++;
cnt[y]++;
union_find(x, y);
}
//判断是否所有点的度都为偶数,如果存在不是偶数的,那么报错
bool flag = true;
for(int i = 1; i <= N; i++)
{
if(cnt[i] % 2 != 0)
{
flag = false;
}
}
if(!flag)
{
printf("%d\n", flag);
continue;
}
//查看所有点是否联通
//先找一个非孤立节点
int t;
for(int i = 1; i <= N; i++)
{
if(cnt[i] != 0)
{
t = i;
break;
}
}
//所有非孤立节点的父节点应该都是一个
int fa = find(t);
for(int i = 1; i <= N; i++)
{
if(find(i) != fa && cnt[i] != 0)
{
flag = false;
break;
}
}
printf("%d\n", flag);
}
return 0;
}