九度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
来源:
2008年浙江大学计算机及软件工程研究生机试真题

 

注意:代码中的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 }

 

posted @ 2015-07-15 15:02  Deribs4  阅读(438)  评论(0编辑  收藏  举报