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;
}

End

posted @ 2021-11-02 16:28  xixike  阅读(30)  评论(1编辑  收藏  举报