种类并查集可以解决多种关系的问题,比如两个人不是朋友的关系,其思想是多开几倍的空间,假如有 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;
}
更新于

请我喝[茶]~( ̄▽ ̄)~*

PocketCat 微信支付

微信支付

PocketCat 支付宝

支付宝