chenfy27的刷题记录

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

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   chenfy27  阅读(14)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示