chenfy27的刷题记录

导航

abc372E K-th Largest Connected Components

有N个顶点的无向图,最初没有边,接下来有Q组询问,格式如下:

  • 1 u v:在顶点u和v之间加一条边;
  • 2 x k: 问与顶点v连通的分量中,顶点编号第k大的是谁?如果不存在,输出-1.
    1<=N,Q<=2E5,1<=u<v<=N, 1<=x<=N, 1<=k<=10

分析:由于k比较小,直接用vector维护连通分量的顶点集合,在合并时,如果顶点数超过k,则只取最大的k个。剩下的就是并查集模板操作。

#include <bits/stdc++.h>
using i64 = long long;

struct DSU {
    void init(int n) {
        fa.resize(n + 1);
        has.resize(n + 1);
        for (int i = 1; i <= n; i++) {
            fa[i] = i;
            has[i].push_back(i);
        }
    }
    int leader(int x) {
        return x == fa[x] ? x : fa[x] = leader(fa[x]);
    }
    void join(int x, int y) {
        x = leader(x);
        y = leader(y);
        if (x != y) {
            if (has[x].size() < has[y].size()) {
                std::swap(x, y);
            }
            for (auto i : has[y]) {
                has[x].push_back(i);
            }
            std::sort(has[x].rbegin(), has[x].rend());
            if (has[x].size() > 10) {
                has[x].resize(10);
            }
            fa[y] = x;
        }
    }
    std::vector<int> fa;
    std::vector<std::vector<int>> has;
};

void solve() {
    int N, Q;
    std::cin >> N >> Q;
    DSU dsu;
    dsu.init(N);
    for (int i = 1; i <= Q; i++) {
        int x, y, z;
        std::cin >> x >> y >> z;
        if (x == 1) {
            dsu.join(y, z);
        } else {
            int u = dsu.leader(y);
            if (z <= dsu.has[u].size()) {
                std::cout << dsu.has[u][z - 1] << "\n";
            } else {
                std::cout << "-1\n";
            }
        }
    }
}

int main() {
    std::cin.tie(0)->sync_with_stdio(0);
    int t = 1;
    while (t--) solve();
    return 0;
}

如果k的范围是[1,N],可以考虑用平衡树来维护连通分量,需要用到启发式合并。

#include <bits/stdc++.h>
using i64 = long long;

// Treap模板...

struct DSU {
    void init(int n) {
        fa.resize(n + 1);
        has.resize(n + 1);
        for (int i = 1; i <= n; i++) {
            fa[i] = i;
            has[i].insert(i);
        }
    }
    int leader(int x) {
        return x == fa[x] ? x : fa[x] = leader(fa[x]);
    }
    void join(int x, int y) {
        x = leader(x);
        y = leader(y);
        if (x != y) {
            if (has[x].size() < has[y].size()) {
                std::swap(x, y);
            }
            has[x].merge(has[y]);
            fa[y] = x;
        }
    }
    std::vector<int> fa;
    std::vector<Treap<int>> has;
};

void solve() {
    int N, Q;
    std::cin >> N >> Q;
    DSU dsu;
    dsu.init(N);
    for (int i = 1; i <= Q; i++) {
        int x, y, z;
        std::cin >> x >> y >> z;
        if (x == 1) {
            dsu.join(y, z);
        } else {
            int u = dsu.leader(y);
            if (z <= dsu.has[u].size()) {
                std::cout << dsu.has[u].Kth(z) << "\n";
            } else {
                std::cout << "-1\n";
            }
        }
    }
}

int main() {
    std::cin.tie(0)->sync_with_stdio(0);
    int t = 1;
    while (t--) solve();
    return 0;
}

posted on 2024-10-07 17:38  chenfy27  阅读(30)  评论(0)    收藏  举报