并查集总结

三部曲 :初始化 合并 查找

目前来说,个人认为最重要的是关系(合并,因为合并的依据是关系)

经典例题

关押罪犯

思路 : 把怨气值从大到小排序,把大的两个人分开,直到两个人再不能分到不同的监狱,此时的怨气值就是要求的

排序简单,问题是怎么合并?设两监狱分别是i(朋友),i+n(敌人),如果是x,y两个人,find(x)  == find(y) 结束了

否则说明两个人还没有在一个集合里,所以x和y的敌人合并,x的敌人和y合并,即 (x,y + n) 和(x + n,y)

#include <bits/stdc++.h>
using namespace std;
const int nn = 2e4 + 10;
const int mm = 1e5 + 10;
int fa[2 * nn];
int n,m,ans;
struct node{
    int x,y,w;
    bool operator <(const node &a){
        return w > a.w;
    }
}e[mm];

int find(int x){
    if(x == fa[x])
        return x;
    return fa[x] = find(fa[x]);
}
void merge(int x,int y){
    fa[find(x)] = find(y);
}
int main(){
    //freopen("in","r",stdin);
    ios::sync_with_stdio(0);
    cin >> n >> m;
    for(int i = 1; i <= 2 * n; i++) fa[i] = i;
    for(int i = 1; i <= m;i++)
        cin >> e[i].x >> e[i].y >> e[i].w;
    sort(e + 1,e+ 1 + m);
    for(int i = 1; i <= m; i++){
        int x = find(e[i].x),y = find(e[i].y);
        if(x == y) {
            ans = e[i].w;break;
        }
        merge(e[i].x,e[i].y + n); merge(e[i].x + n,y);

    }
    cout << ans;
    return 0;
}
View Code

食物链          

原文地址:https://www.cnblogs.com/xcfxcf/p/13374686.html