-
欧拉回路是指不令笔离开纸面,可画过图中每条边仅一次,且可以回到起点的一条回路。现给定一个图,问是否存在欧拉回路?
-
测试输入包含若干测试用例。每个测试用例的第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)有向图:保证图是连通图,而且每个节点的入度必须等于出度;
(2)无向图:保证图是连通图,且每个节点的度数必须为偶数(不能为0);
这道题目中显然是无向图,不过用到的算法主要是并查集,各位若不明白并查集,可参考这篇博客:http://blog.csdn.net/cfreezhan/article/details/8629871
好了,废话少说,上代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const int Max = 1010;
int parent[Max]; //用来存储父亲节点
int rank[Max]; //用来存储每个节点的度
int find(int x)
{
return x == parent[x] ? x : parent[x] = find(parent[x]); //找该节点的父亲节点,用递归形式
}
void Union(int x, int y)//合并
{
x = find(x);
y = find(y);
if(x == y)
return;
else
parent[x] = y;
}
int main()
{
int n, m;
while(~scanf("%d", &n))
{
if(n == 0)
break;
scanf("%d", &m);
memset(rank, 0, sizeof(rank));//度全部初始化为0
for(int i = 1; i <= n; i++)
parent[i] = i; //开始时自己是自己的根节点
for(int i = 1; i <= m; i++)
{
int s, e;
scanf("%d %d", &s, &e);
rank[s]++;
rank[e]++;
Union(s, e);//每读入一条边就合并一次 ,这样能提高效率不少
}
int root = 0;//如果是有欧拉回路,则最终只有一个根节点
for(int i= 1; i <= n; i++)
if(i == parent[i])
root++;
if(root != 1)
{
printf("0\n");//如果根结点不是一个
continue;//则不存在,继续进行下一组数据
}
int flag = 1;
for(int i = 1; i <= n; i++)
if(rank[i] % 2 != 0)
{
flag = 0;
break;
}
if(flag)
printf("1\n");
else
printf("0\n");
}
//system("pause");
return 0;
}