种类并查集可以解决多种关系的问题,比如两个人不是朋友的关系,其思想是多开几倍的空间,假如有 n 种关系,就开 n 倍的空间,然后用 + n 来表示两个不同集合的关系
# 食物链 P2024
链接:https://www.luogu.com.cn/problem/P2024

开 3 倍空间维护 3 个集合,分别表示 A、B、C,例如 1 和 2 是朋友,那就把 3 个集合中的 1 和 2 合并,1 吃 2,就把 A 集合中 1 和 B 集合中的 2 合并,B 集合中的 1 和 C 集合的 2 合并,C 集合的 1 和 A 集合的 2 合并,再来一个 2 吃 3,这样一来 C 中的 3 和 A 中的 1 也在一个集合里了,维护了 C 吃 A 的关系,也就是如果 Ai 和 Bj 的祖先相同就表示 Ai 吃 Bj,另外两个同理
# CODE
#include <bits/stdc++.h> | |
#define debug freopen("in.txt","r",stdin); freopen("out.txt","w",stdout) | |
#define ios ios::sync_with_stdio(0);cin.tie(0);cout.tie(0) | |
using namespace std; | |
typedef long long ll; | |
typedef unsigned long long ull; | |
const int MAXN=20010; | |
const double pi=acos(-1); | |
const int MOD=1e9+7; | |
const int INF=0x3f3f3f3f; | |
const int SUB=-0x3f3f3f3f; | |
const int eps=1e-4; | |
struct node{ | |
int u,v,w; | |
}arr[MAXN]; | |
int n,m; | |
int fa[MAXN*2]; | |
int find(int x){ | |
if(x==fa[x]) return x; | |
else return fa[x]=find(fa[x]); | |
} | |
void remerge(int x,int y){ | |
int fx=find(x),fy=find(y); | |
if(fx!=fy) fa[fx]=fy; | |
} | |
bool cmp(node a,node b){ | |
return a.w>b.w; | |
} | |
int main(){ | |
ios; | |
cin>>n>>m; | |
for(int i=1;i<=m;i++) cin>>arr[i].u>>arr[i].v>>arr[i].w; | |
sort(arr+1,arr+1+m,cmp); | |
for(int i=1;i<=2*n;i++) fa[i]=i; | |
for(int i=1;i<=m;i++){ | |
int x=arr[i].u,y=arr[i].v; | |
if(find(x)==find(y) || find(x+n)==find(y+n)){ | |
cout<<arr[i].w<<'\n'; | |
return 0; | |
} | |
remerge(x+n,y); | |
remerge(x,y+n); | |
} | |
cout<<0<<'\n'; | |
return 0; | |
} |