CF #541div2 F

题目本质:并查集的链式合并

解决方法1:

类似哈夫曼树,叶节点们为真点,其余造一些虚的父节点,使得dfs这棵树的时候,先进行并查合并的点一定是兄弟节点因而紧挨着被输出,巧妙达到了效果。

 1 #pragma comment(linker, "/STACK:1024000000,1024000000")
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <cmath>
 6 #include <ctime>
 7 #include <cctype>
 8 #include <climits>
 9 #include <iostream>
10 #include <iomanip>
11 #include <algorithm>
12 #include <string>
13 #include <sstream>
14 #include <stack>
15 #include <queue>
16 #include <set>
17 #include <map>
18 #include <vector>
19 #include <list>
20 #include <fstream>
21 #define ri readint()
22 #define gc getchar()
23 #define R(x) scanf("%d", &x)
24 #define W(x) printf("%d
", x)
25 #define init(a, b) memset(a, b, sizeof(a))
26 #define rep(i, a, b) for (int i = a; i <= b; i++)
27 #define irep(i, a, b) for (int i = a; i >= b; i--)
28 #define ls p << 1
29 #define rs p << 1 | 1
30 using namespace std;
31 
32 typedef double db;
33 typedef long long ll;
34 typedef unsigned long long ull;
35 typedef pair<int, int> P;
36 const int inf = 0x3f3f3f3f;
37 const ll INF = 1e18;
38 
39 inline int readint() {
40     int x = 0, s = 1, c = gc;
41     while (c <= 32)    c = gc;
42     if (c == '-')    s = -1, c = gc;
43     for (; isdigit(c); c = gc)
44         x = x * 10 + c - 48;
45     return x * s;
46 }
47 
48 const int maxn = 15e4 + 5;
49 int n, fa[maxn << 1], l[maxn << 1], r[maxn << 1];
50 
51 inline int find(int v) {
52     return v == fa[v] ? v : fa[v] = find(fa[v]);
53 }
54 
55 void dfs(int cur) {
56     if (!l[cur] && !r[cur]){
57         printf("%d ", cur);
58         return;
59     }
60     if (l[cur])    dfs(l[cur]);
61     if (r[cur])    dfs(r[cur]);
62 }
63 
64 int main() {
65     n = ri;
66     rep(i, 1, n) {
67         fa[i] = i;
68     }
69     rep(i, 1, n - 1) {
70         int a = ri, b = ri;
71         a = find(a), b = find(b);
72         fa[a] = fa[b] = fa[n + i] = n + i;
73         l[n + i] = a, r[n + i] = b;
74     }
75     dfs(n + n - 1);
76     return 0;
77 }

解决方法2:

正常地用数组记录链,l和r记录真实的左右顺序,并查集式的getl和getr记录这个链上的最左端和最右端,两个集合并时一接。貌似直接把常规并查集的father数组扔了……

大佬代码:

 1 int n,m,i,j,k,a[150005],l[150005],r[150005],fl[150005],fr[150005],x,y;
 2 int gfl(int x){if (fl[x]==x) return x;return fl[x]=gfl(fl[x]);}
 3 int gfr(int x){if (fr[x]==x) return x;return fr[x]=gfr(fr[x]);}
 4 int main()
 5 {
 6     read(n);
 7     rep(i,n)
 8     {
 9         fl[i]=fr[i]=l[i]=r[i]=i;
10     }
11     rep(i,n-1)
12     {
13         read(x);read(y);
14         x=gfr(x);y=gfl(y);
15         r[x]=y;l[y]=x;
16         fr[x]=y;fl[y]=x; 
17     }
18     x=gfl(1);
19     rep(i,n)
20     {
21         printf("%d ",x);
22         x=r[x];
23     }
24     return 0;
25 }
原文地址:https://www.cnblogs.com/AlphaWA/p/10434337.html