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;
}