九度oj题目1027:欧拉回路
题目1027:欧拉回路
时间限制:1 秒
内存限制:32 兆
特殊判题:否
提交:2844
解决:1432
- 题目描述:
-
欧拉回路是指不令笔离开纸面,可画过图中每条边仅一次,且可以回到起点的一条回路。现给定一个图,问是否存在欧拉回路?
- 输入:
-
测试输入包含若干测试用例。每个测试用例的第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
注意:代码中的i要从1开始,要与题目匹配!!
欧拉回路定义:
若图G中存在这样一条路径,使得它恰通过G中每条边一次,则称该路径为欧拉路径。若该路径是一个圈(首尾相连),则称为欧拉(Euler)回路。
判断是否存在欧拉回路的准则:
有向图:图连通,所有的顶点出度=入度。
无向图:图连通,所有顶点都是偶数度。
程序实现一般是如下过程:
1.利用并查集判断图是否连通,即判断p[i] < 0的个数,如果大于1,说明不连通。
2.根据出度入度个数,判断是否满足要求。
3.利用dfs输出路径。
学习代码:
1 /*************************************************** 2 3 题目描述: 4 欧拉回路是指不令笔离开纸面,可画过图中每条边仅一次,且可以回到起点的一条回路。现给定一个图,问是否存在欧拉回路? 5 6 输入: 7 测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是节点数N ( 1 < N < 1000 )和边数M;随后的M行对应M条边,每行给出一对正整数,分别是该条边直接连通的两个节点的编号(节点从1到N编号)。当N为0时输入结束。 8 9 输出: 10 每个测试用例的输出占一行,若欧拉回路存在则输出1,否则输出0。 11 12 样例输入: 13 14 3 3 15 1 2 16 1 3 17 2 3 18 3 2 19 1 2 20 2 3 21 0 22 23 样例输出: 24 25 1 26 0 27 28 29 **************************************************/ 30 #include <cstdio> 31 #include <cstring> 32 33 using namespace std; 34 35 const int N = 1000 + 10; 36 37 int n, m; 38 int g[N][N]; 39 int degree[N]; 40 int p[N]; 41 42 int union_find(int x); 43 void disjoint_union(int a, int b); 44 bool check(); 45 46 int main() 47 { 48 #ifndef ONLINE_JUDGE 49 freopen("e:\\uva_in.txt", "r", stdin); 50 #endif // ONLINE_JUDGE 51 52 while (scanf("%d", &n) == 1) 53 { 54 if (n == 0) 55 break; 56 57 scanf("%d", &m); 58 memset(degree, 0, sizeof(degree)); 59 memset(p, -1, sizeof(p)); 60 61 for (int i = 0; i < m; i++) { 62 int a, b; 63 scanf("%d%d", &a, &b); 64 degree[a]++; 65 degree[b]++; 66 disjoint_union(a, b); 67 } 68 69 if (check()) 70 printf("1\n"); 71 else 72 printf("0\n"); 73 } 74 return 0; 75 } 76 77 int union_find(int x) 78 { 79 if (p[x] < 0) 80 return x; 81 82 return p[x] = union_find(p[x]); 83 } 84 85 void disjoint_union(int a, int b) 86 { 87 int pa = union_find(a); 88 int pb = union_find(b); 89 90 if (pa == pb) 91 return; 92 93 if (pa < pb) 94 p[pb] = pa; 95 else 96 p[pa] = pb; 97 } 98 99 bool check() 100 { 101 int cnt = 0; 102 for (int i = 1; i <= n; i++) { 103 cnt += (p[i] < 0); 104 if (degree[i] & 1) 105 return false; 106 } 107 108 if (cnt != 1) 109 return false; 110 111 return true; 112 }
自己的代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <string> 4 #include <queue> 5 #include <vector> 6 #include <stack> 7 #include <iostream> 8 using namespace std; 9 int fa[1005],degree[1005]; 10 int findfa(int a){ 11 if(fa[a]!=a){ 12 fa[a]=findfa(fa[a]); 13 } 14 return fa[a]; 15 } 16 int main(){ 17 //freopen("D:\\INPUT.txt","r",stdin); 18 int n,m; 19 while(scanf("%d",&n)!=EOF){ 20 if(!n){ 21 break; 22 } 23 memset(degree,0,sizeof(degree)); 24 scanf("%d",&m); 25 int i; 26 for(i=0;i<=n;i++){ 27 fa[i]=i; 28 } 29 int u,v; 30 for(i=0;i<m;i++){ 31 scanf("%d %d",&u,&v); 32 degree[u]++; 33 degree[v]++; 34 int fu=findfa(u); 35 int fv=findfa(v); 36 if(fu>fv){ 37 fa[fv]=fu; 38 } 39 else{ 40 fa[fu]=fv; 41 } 42 } 43 int num=0; 44 for(i=1;i<=n;i++){ 45 if(fa[i]==i){ 46 num++; 47 } 48 } 49 if(num!=1){//整体不联通,整个图不止一个集合.好好体会!! 50 cout<<0<<endl; 51 continue; 52 } 53 int odd=0; 54 for(i=1;i<=n;i++){ 55 if(degree[i]%2){ 56 odd++; 57 } 58 } 59 if(odd){//不是所有点的度数均为偶数 60 cout<<0<<endl; 61 continue; 62 } 63 //全图联通并且所有点的度数均为偶数 64 cout<<1<<endl; 65 } 66 return 0; 67 }