从大到小排序,依次找出最大的怨气值,使得所有罪犯对可以被分到两个监狱。采用贪心 + 并查集维护对立关系,若某对罪犯已在同一集合,无法分到不同监狱,则该怨气值就是最大的怨气值。
#include<bits/stdc++.h>
using namespace std;
struct E {
int x, y, z;
};
E f[100005]; // 存储罪犯怨气关系
int n, m;
int a[20005]; // 并查集父节点数组
int b[20005]; // 记录对立监狱的罪犯
// 按怨气值降序排序
bool cmp(E a, E b) {
return a.z > b.z;
}
int gf(int x) {
if (a[x] == x) return x;
a[x] = gf(a[x]);
return a[x];
}
void ad(int x, int y) {
x = gf(x);
y = gf(y);
a[x] = y;
}
// 检查x和y是否在同一集合
bool check(int x, int y) {
return gf(x) == gf(y);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n >> m;
// 并查集初始化
for (int i = 1; i <= n; i++) a[i] = i;
for (int i = 1; i <= m; i++) {
cin >> f[i].x >> f[i].y >> f[i].z;
}
// 按怨气值降序排序
sort(f + 1, f + m + 1, cmp);
// 遍历处理罪犯对
for (int i = 1; i <= m; i++) {
// 若x和y已连通,输出当前怨气值
if (check(f[i].x, f[i].y)) {
cout << f[i].z;
break;
} else {
// 记录x的对立罪犯,已有则合并
if (!b[f[i].x]) {
b[f[i].x] = f[i].y;
} else {
ad(b[f[i].x], f[i].y);
}
// 记录y的对立罪犯,已有则合并
if (!b[f[i].y]) {
b[f[i].y] = f[i].x;
} else {
ad(b[f[i].y], f[i].x);
}
}
}
return 0;
}

京公网安备 11010502036488号