扩展域并查集(不会二分图 QAQ)
因为一个罪犯有朋友和仇人,需要开2倍大小的并查集,表示朋友域和仇人域
我们先按照两个人之间的仇恨从大到小排序,先解决大的仇恨,直到有仇恨无法解决,这样使得发生的冲突尽可能小
先判断a和b是否是朋友(即在一个集合中),如果已经在一个集合中,说明当前的冲突无法避免
如果不是朋友,那么就进行:
1)合并a和b的仇人域(表示a和b的仇人是朋友,关入同一个监狱)
2)合并a的仇人域和b(表示a的仇人和b是朋友,关入同一个监狱)
#include <bits/stdc++.h>
using namespace std;
const int N = 4e4 + 5, M = 1e5 + 5;
int fa[N];
struct node {
int a, b, c;
bool operator < (const node &b) const {
return c > b.c;
}
} arr[M];
void init(int n)
{
for (int i = 1; i <= n; i++)
fa[i] = i;
}
int find(int x)
{
if (fa[x] == x) return x;
return fa[x] = find(fa[x]);
}
void unite(int x, int y)
{
x = find(x), y = find(y);
fa[x] = y;
}
int main(void)
{
int n, m;
cin >> n >> m;
init(n);
for (int i = 0; i < m; i++) {
scanf("%d%d%d", &arr[i].a, &arr[i].b, &arr[i].c);
}
sort(arr, arr + m);
int res = 0;
int a, b;
for (int i = 0; i < m; i++) {
a = arr[i].a, b = arr[i].b;
if (find(a) == find(b)) {
res = arr[i].c;
break;
}
unite(a, b + n);
unite(a + n, b);
}
cout << res << endl;
return 0;
}