The Necklace
题目链接:http://acm.bnu.edu.cn/bnuoj/problem_show.php?pid=18472
题目大意:
有一些珍珠(最多1000个),珍珠的两头有颜色(颜色最多50种,编号为1到50),现在问你能否将珍珠按照一定的规律串成一串项链?如果可以,则输出应该如何安排珍珠的先后顺序,否则输出不行。
规律是:前一个珍珠的尾色必须和后一个珍珠的前色相同,而且最后一个珍珠的尾色必须和第一个珍珠的前色相同。
解题思路:
这是一道关于欧拉回路的题目。
首先颜色表示无向图的顶点,而一颗珍珠代表了一条边,(由于珍珠前色和尾色可以互掉,故为无向图)。问该图是否为欧拉回路。
欧拉回路:
欧拉回路的特点是所有顶点的度数均为偶数。 用递归的方式打印欧拉回路。
并查集判连通性:
同时需要用并查集判断连通性。
#include<iostream> #include<fstream> #include<cstdio> #include<cstring> #include<cmath> #include<map> #include<queue> #include<stack> #include<vector> #include<set> #include<ctype.h> #include<algorithm> #include<string> #define PI acos(-1.0) #define maxn 1000 #define INF 1<<25 #define mem(a, b) memset(a, b, sizeof(a)) typedef long long ll; using namespace std; int g[55][55], n; int f[55]; struct node { int u, v; }; stack<node> s; int find(int x) { if (f[x] != x) f[x] = find(f[x]); return f[x]; } void euler(int u) { for (int v = 1; v <= 50; v++) if (g[u][v]) { g[u][v]--, g[v][u]--; euler(v); node tmp; tmp.u = u, tmp.v = v; s.push(tmp); } } int main () { int t, i, j, cas = 1; cin>>t; while(t--) { cin>>n; mem(g, 0); int u, v; for (i = 1; i <= 50; i++) f[i] = i; int has[55] = {0}, du[55] = {0}, k; for (i = 0; i < n; i++) { scanf("%d%d", &u, &v); g[u][v] ++; g[v][u] ++; has[u]++, has[v]++; du[u]++, du[v]++; f[find(u)] = find(v); k = u; } int sum = 0; for (i = 1; i <= 50; i++) if (has[i] && f[i] == i) sum++; if (cas != 1) puts(""); printf("Case #%d\n", cas++); bool flag = true; for (i = 1; i <= 50; i++) if (du[i] % 2 == 1) flag = false; if (sum != 1 || !flag) puts("some beads may be lost"); else { euler(k); while(!s.empty()) { node tmp = s.top(); s.pop(); printf("%d %d\n", tmp.u, tmp.v); } } } return 0; }