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; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】