CF1131F Asya And Kittens 题解
Description
Solution
感觉题解区的各位大佬代码都写麻烦了(sto @SGColin 学长 orz)。
还是并查集的做法,但是连边的时候直接连即可。
首先开 \(n\) 个 vector,假设当前要让联通快 \(x\) 和 \(y\) 相邻(\(x\) 和 \(y\) 不在同一个联通快内),我们直接把 find(y)
插入到 g[find(x)]
即可。
也就是 g[find(x)].push_back(find(y));
输出时,先随便 find 一个点(此时所有点已经在同一联通块中了,所以可以随意 find),然后枚举这个点的 vector,递归输出。
考虑正确性,由于我们是按顺序合并的,所以 vector 中排名靠前的和当前点挨得更近,且 vector 中的每一个点都是一个联通块,所以递归输出。
代码就很简单啦。
Code
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 2e5;
int n;
int f[N];
vector <int> g[N];
inline int find(int x){
return f[x] == x ? x : f[x] = find(f[x]);
}
inline void print(int s){
for(auto x : g[s]){
printf("%d ", x);
if(g[x].size()) print(x);
}
}
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; ++i)
f[i] = i;
for(int i = 1, x, y; i < n; ++i){
scanf("%d%d", &x, &y);
int fx = find(x), fy = find(y);
if(fx != fy){
f[fy] = fx;
g[fx].push_back(fy);
}
}
int s = find(1);
printf("%d ", s);
print(s);
puts("");
return 0;
}