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