NYOJ--42--dfs水过||并查集+欧拉通路--一笔画问题

dfs水过:

 1 /*
 2     Name: NYOJ--42--一笔画问题
 3     Author: shen_渊 
 4     Date: 18/04/17 15:22
 5     Description: 这个题用并查集做,更好。在练搜索,试试手 
 6                 本来用的vector存放边,结果,vector并不能当做数组,遍历的时候只能用迭代器
 7                 中间没有数据的部分读取会出错 
 8 输入
 9 第一行只有一个正整数N(N<=10)表示测试数据的组数。
10 每组测试数据的第一行有两个正整数P,Q(P<=1000,Q<=2000),分别表示这个画中有多少个顶点和多少条连线。
11 (点的编号从1到P)
12 随后的Q行,每行有两个正整数A,B(0<A,B<P),表示编号为A和B的两点之间有连线。
13 输出
14 如果存在符合条件的连线,则输出"Yes",
15 如果不存在符合条件的连线,输出"No"。
16 */
17 #include<bits/stdc++.h> 
18 using namespace std;
19 void dfs(int);
20 int vis[1005];
21 int vec[1005][1005];
22 int outDegree[1005];
23 int N,P,Q,flag;
24 int main(){
25     int N;cin>>N; 
26     while(N--){
27         flag = 0;
28         memset(vec,0,sizeof(vec));
29         memset(vis,0,sizeof(vis));
30         memset(outDegree,0,sizeof(outDegree));
31         cin>>P>>Q;
32         for(int i=0; i<Q; ++i){
33             int x,y;cin>>x>>y;
34             vec[x][y] = vec[y][x] = 1;
35         }
36         dfs(1);
37         int mark = 0;
38         for(int i=1; i<=P; ++i){
39             if(outDegree[i] == 0){
40                 mark = 1;break;
41             } 
42             if(outDegree[i]%2)flag++;
43         }
44         if(mark)cout<<"No"<<endl;
45         else if(flag == 0 || flag == 2)cout<<"Yes"<<endl;
46         else cout<<"No"<<endl;
47     }
48     return 0;
49 }
50 void dfs(int i){
51     vis[i] = 1;
52     for(int k=1; k<=P; ++k){
53         if(vec[i][k]){
54             outDegree[i]++;
55             if(!vis[k])
56                 dfs(k);
57         }
58     }
59 }

学到图论了,用并查集+欧拉做一次:

 1  
 2 /*
 3     欧拉路径,无向图
 4     1判断是否为连通图, 
 5     2判断奇点的个数为0或2按照题意,只要是欧拉回路或者通路都符合题意 
 6 */
 7 #include <iostream> 
 8 #include <cstring>
 9 #include <vector>
10 #include <cstdio>
11 using namespace std;
12 int edge[2010];
13 struct DisjoinSet {
14     vector<int> father, rank;
15     
16     DisjoinSet(int n): father(n), rank(n) {
17         for (int i=0; i<n; i++) {
18             father[i] = i;
19         }
20     }
21     
22     int easy_find(int v)  {//非递归 
23         int k, j, r;
24         r = v;
25         while (r!=father[r]) {
26             r = father[r];
27         }
28         k = v;
29         while (k!=r) {
30             j = father[k];
31             father[k] = r;
32             k = j;
33         }
34         return r;
35     }
36     void merge(int x, int y) {
37         int a = easy_find(x), b = easy_find(y);
38         if (rank[a] < rank[b]) {
39             father[a] = b;
40         } else {
41             father[b] = a;
42             if (rank[b] == rank[a]) {
43                 ++rank[a];
44             }
45         }
46     }
47 } ; 
48 
49 int p, q;
50 int main()
51 {
52 //    freopen("in.txt", "r", stdin);
53     int N;
54     scanf("%d", &N);
55     while (N--) {
56         memset(edge, 0, sizeof(edge));
57         scanf("%d %d", &p, &q);
58         DisjoinSet mfs(2010);
59         for (int i=0; i<q; i++) {
60             int a, b;
61             scanf("%d %d", &a, &b);
62             edge[a]++;
63             edge[b]++;
64             mfs.merge(a, b);
65         }
66         int father = mfs.easy_find(1);
67         int ct = 0;
68         for (int i=1; i<=p; i++) {
69             if (mfs.father[i] != father) {
70                 ct = -1;
71                 break;
72             }
73             if (edge[i] & 1) ct++;
74         }
75         if (ct == 0 || ct == 2) printf("Yes\n");
76         else printf("No\n");
77     }
78     return 0;
79 }        

 

posted @ 2017-04-18 15:28  朤尧  阅读(378)  评论(0编辑  收藏  举报