openjudge欧拉回路

Written by Robert_Wang in Southwest University of Science And Technology.

7:欧拉回路

总时间限制: 
1000ms
内存限制: 
65536kB
描述

欧拉回路是指不令笔离开纸面,可画过图中每条边仅一次,且可以回到起点的一条回路

给定一个无向图,请判断该图是否存在欧拉回路

输入
输入数据包含若干测试用例
每个测试用例的第一行是两个正整数,分别表示图的节点数N(1 < N < 1000)和边数M
随后的M行对应M条边,每行有两个正整数,分别表示这条边上的两个节点的编号(节点编号从1到N)
当N为0时输入结束
输出
每个测试用例的输出占一行,若存在欧拉回路则输出1,否则输出0
样例输入
3 31 21 32 33 21 22 30
样例输出
10


分析:这是一个判断无向图回路的简单操作,只需要满足两点即可

1:该图联通,用程序的话就是说联通子图只有一个

2:该图的每一个节点的度为偶数。

用并查集来检查1;

用数组记录节点次数来检查2;

#include<iostream>
#include<string.h>
using namespace std;
#define MAXV 1001
#define INF 299999
int ans[MAXV + 1];
int a[MAXV + 1][MAXV + 1];
typedef struct
{
	int No;
	int parent;
	int rank;
}UFStree;
void Make_Set(UFStree t[], int n)
{
	int i;
	for (i = 1; i <= n; i++)
	{
		t[i].No = i;
		t[i].parent = i;//自身父母作为下面的查找依据
		t[i].rank = 0;//该集合的秩,用于后面建立平衡树
	}
}
int Find_Set(UFStree t[], int x)
{
	if (x == t[x].parent)	return x;
	return Find_Set(t,t[x].parent);
}
void Union(UFStree t[], int x, int y)
{
	int x1 = Find_Set(t,x);
	int y1 = Find_Set(t,y);
	if (t[x1].rank>t[y1].rank)//x1的树高,则作为父母
	{
		t[y].parent = x;
	}
	else
	{
		t[x].parent = y;
		if (t[x1].rank == t[y1].rank) t[x1].rank++;
	}
}
bool Even()//结点为偶数的判定
{
	int i;
	for (i = 1; i <= MAXV; i++)
	{
		if (ans[i] % 2) return false;
	}
	return true;
}
bool Unicom(UFStree t[], int n)
{
	int i,c=0;
	for (i = 1; i <= n; i++)
	{
		if (Find_Set(t, i) == i) c++;
		if (c > 1) return false;//联通子图为1, 则整个图联通
	}
	return true;
}
int main()
{
	int n, e, i, j, x, y;
	UFStree b[MAXV];
	while (cin >> n)
	{
		if (!n) break;//输入0表示结束
		memset(a, 0, sizeof(a));
		memset(ans, 0, sizeof(ans));
		Make_Set(b, n);
		cin >> e;
		int t = 0;
		for (i = 1; i <= e; i++)
		{
			cin >> x >> y;
			if (!t) t = x;
			a[x][y] = 1;//由于是无向图,所以a[x][y] = a[y][x] = 1;
			a[y][x] = 1;
			ans[x]++;
			ans[y]++;
			if (Find_Set(b, x) != Find_Set(b, y)) Union(b, x, y);//若不连通,则将其联通
		}
		if (Even() && Unicom(b,n)) cout << 1 << endl;//如果图联通并且每个结点为偶数,则存在欧拉回路
		else cout << 0 << endl;//反之,不存在
	}
	return 0;
}

显然,上面的代码层次分明,但是我们在做题的时候,其实可以更加简洁一下;

#include<iostream>
#include<string.h>
using namespace std;
#define MAXV 1001
int degrees[MAXV + 1];
int UFS[MAXV+1];//并查集
int Find_UFS(int x)
{
	if (UFS[x] == -1) return x;
	else return Find_UFS(UFS[x]);
}
int main()
{
	int n, e, i, j, x, y,x1,y1;
	while (cin >> n)
	{
		if (!n) break;//输入0表示结束
		memset(UFS, -1, sizeof(UFS));//并查集的查找属性标记为-1
		memset(degrees, 0, sizeof(degrees));
		cin >> e;
		for (i = 1; i <= e; i++)
		{
			cin >> x >> y;
			x1 = Find_UFS(x);
			y1 = Find_UFS(y);
			if (x1!=y1) UFS[x1] = y1;
			degrees[x]++;
			degrees[y]++;
		}
		int mark = 1;
		int c = 0;
		for (i = 1; i <= n; i++)
		{
			if(degrees[i]%2)
			{
				mark = 0;
				break;
			}
			if (Find_UFS(i) == i) c++;//联通子图的个数为1,则整个图联通
			if (c > 1) { mark = 0; break; }
		}
		cout << mark << endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40883132/article/details/79913618