并查集总结
三部曲 :初始化 合并 查找
目前来说,个人认为最重要的是关系(合并,因为合并的依据是关系)
经典例题
思路 : 把怨气值从大到小排序,把大的两个人分开,直到两个人再不能分到不同的监狱,此时的怨气值就是要求的
排序简单,问题是怎么合并?设两监狱分别是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; }