题意:
妹妹有一条项链,这条项链由许多珠子串在一起组成,珠子是彩色的,两个连续的珠子的交汇点颜色相同,也就是对于相邻的两个珠子来说,前一个珠子的末端颜色和后一个珠子的首端颜色相同。有一天,项链断了,珠子洒落了一地,到处都是,妹妹使出浑身解数把地板上能看到的珠子(5-1000)都捡了起来,但是不确定是否收集齐了。给你他妹妹收集的珠子的两端的颜色编号(1 - 50),让你判断是否收集齐了。
思路:
把颜色看成点,把一个珠子看成一个无向边,则问题有解,当且仅当图中存在欧拉回路。于是先判断由题意构建出来的无向图是否存在欧拉回路,无向图能否构建出来欧拉回路需要满足两个条件:
1:底图连通,可以用并查集或者DFS判断,这里利用并查集了。
2:不存在度数为奇数的点。
判断完成后,利用DFS遍历整个图,每访问一个点就把这个点压入栈中,回溯时弹出来当前点并记录下来。随后得到的就是欧拉回路的点的顺序,连续的两个点就是问题需要输出的边。
代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cmath> 6 #include <algorithm> 7 #include <stack> 8 #include <queue> 9 using namespace std; 10 11 const int maxV = 50; 12 const int maxE = 1000; 13 int degree[maxV + 7]; 14 int pre[maxV + 7]; 15 int head[maxV + 7]; 16 int vis[maxE * 2 + 7]; 17 int E, V; 18 19 struct EdgeNode 20 { 21 int to; 22 int next; 23 }edges[2 * maxE + 7]; 24 25 void initPre() 26 { 27 for(int i = 1; i <= maxV; i++)pre[i] = i; 28 } 29 30 int Find(int x) 31 { 32 return x == pre[x] ? x : pre[x] = Find(pre[x]); 33 } 34 35 void mix(int x, int y) 36 { 37 int fx = Find(x); 38 int fy = Find(y); 39 if(fx != fy) pre[fx] = fy; 40 } 41 42 int isEuler() 43 { 44 for(int i = 1; i <= maxV; i++) 45 if(degree[i] & 1) return 0; 46 return 1; 47 } 48 49 int isConnct() 50 { 51 int cnt = 0; 52 for(int i = 1; i <= maxV; i++) 53 if(degree[i] && pre[i] == i) cnt++; 54 if(cnt == 1) return 1; 55 return 0; 56 } 57 58 stack<int> eu; 59 int ans[maxE + 7]; 60 int len; 61 void eulerDFS(int now) 62 { 63 eu.push(now); 64 for(int k = head[now]; k != -1; k = edges[k].next) 65 { 66 if(!vis[k]) 67 { 68 vis[k] = 1; 69 if(k & 1) vis[k + 1] = 1; 70 else vis[k - 1] = 1; 71 eulerDFS(edges[k].to); 72 } 73 } 74 ans[++len] = eu.top();//储存欧拉回路点的序列 75 eu.pop(); 76 } 77 78 int main() 79 { 80 //freopen("in.txt", "r", stdin); 81 int T; 82 scanf("%d", &T); 83 int kas = 0; 84 while(T--) 85 { 86 scanf("%d", &E); 87 memset(degree, 0, sizeof(degree)); 88 memset(edges, 0, sizeof(EdgeNode)); 89 memset(head, -1, sizeof(head)); 90 initPre(); 91 int st = 51;//默认路径起点 92 for(int i = 1; i <= E; i++) 93 { 94 int u, v; 95 scanf("%d%d", &u, &v); 96 edges[2 * i - 1].to = v;//链式前向星存储无向图的边需正反各存一次 97 edges[2 * i - 1].next = head[u]; 98 head[u] = 2 * i - 1; 99 edges[2 * i].to = u; 100 edges[2 * i].next = head[v]; 101 head[v] = 2 * i; 102 degree[u]++; 103 degree[v]++; 104 mix(u, v); 105 st = min(st, min(u, v)); 106 } 107 printf("Case #%d\n", ++kas); 108 if(isConnct() && isEuler()) 109 { 110 memset(vis, 0, sizeof(vis)); 111 memset(ans, 0, sizeof(ans)); 112 len = 0; 113 eulerDFS(st); 114 for(int i = 1; i < len; i++)//两个相邻的点构成一条边 115 printf("%d %d\n", ans[i], ans[i + 1]); 116 } 117 else 118 printf("some beads may be lost\n"); 119 if(T)printf("\n"); 120 } 121 return 0; 122 }
(PS:不只是题意没理解透还是什么,如果妹妹没捡起来的刚好也构成了欧拉回路,那么岂不是还是没收集齐嘛,不过等串起来应该会发现的 (逃......)
时间: 2024-10-21 08:30:31