种类并查集可以解决多种关系的问题,比如两个人不是朋友的关系,其思想是多开几倍的空间,假如有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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| #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; }
|