关押罪犯(扩展域并查集)

在这里插入图片描述
在这里插入图片描述
扩展域并查集(不会二分图 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;
}

猜你喜欢

转载自blog.csdn.net/weixin_43772166/article/details/113096029