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 }