Problem Description
欧拉回路是指不令笔离开纸面,可画过图中每条边仅一次,且可以回到起点的一条回路。现给定一个图,问是否存在欧拉回路?
Input
测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是节点数N ( 1 < N < 1000 )和边数M;随后的M行对应M条边,每行给出一对正整数,分别是该条边直接连通的两个节点的编号(节点从1到N编号)。当N为0时输入结
束。
束。
Output
每个测试用例的输出占一行,若欧拉回路存在则输出1,否则输出0。
Sample Input
3 3
1 2
1 3
2 3
3 2
1 2
2 3
0
1 2
1 3
2 3
3 2
1 2
2 3
0
Sample Output
1
0
0
这道题是欧拉回路的基础题,需要用到两部分:并查集 + 欧拉回路判定定理 。 并查集判断图是否连通 ,欧拉回路判定定理:在一个连通图G中存在欧拉回路的充要条件是图G中不存在奇度顶点。
请看代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<queue>
using namespace std ;
const int MAXN = 1005 ;
int set[MAXN] ;
int d[MAXN] ; // 存顶点的度
inline void RD (int &a) // 输入优化
{
a = 0 ;
char t ;
while ((t = getchar()) && t >= '0' && t <= '9')
{
a = a * 10 + t - '0' ;
}
}
int find(int x) // 并查集
{
int r = x ;
while ( r != set[r] )
{
r = set[r] ;
}
return r ;
}
int main()
{
int n , m ;
while (1)
{
RD(n) ;
if(n == 0)
break ;
memset(set , 0 , sizeof(set)) ;
memset(d , 0 , sizeof(d)) ;
RD(m) ;
int i ;
for(i = 1 ; i <= n ; i ++) // 初始化并查集
{
set[i] = i ;
}
for(i = 0 ; i < m ; i ++)
{
int a , b ;
RD(a) ;
RD(b) ;
d[a] ++ ;
d[b] ++ ;
int ta , tb ;
ta = find(a) ;
tb = find(b) ;
if(ta < tb)
{
set[tb] = ta ;
}
else
set[ta] = tb ;
}
int sumj = 0 ;
int fz = 0 ;
for(i = 1 ; i <= n ; i ++)
{
if(set[i] == i)
{
fz ++ ;
}
if(d[i] % 2 == 1)
{
sumj ++ ;
}
}
if(fz > 1 || sumj > 0)
{
printf("0\n") ;
}
else
{
printf("1\n") ;
}
}
return 0 ;
}