算法竞赛备赛——【数据结构】并查集

并查集

普通并查集

注意根据数据大小来开int 或者 long long 否则容易MLE

树的存储结构 双亲表示法------数组 孩子表示法 孩子兄弟表示法

P3367 【模板】并查集 - 洛谷

C++ 复制代码
#include <bits/stdc++.h>
using ll=long long;
using namespace std;
const int N=2e5+5; 

int fa[N];
int n,m;

int find(int x){
	if(x==fa[x])
		return x;
	else return fa[x]=find(fa[x]);
} 
 
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;++i){
		fa[i]=i;
	}
	for(int i=0;i<m;++i){
		int z,x,y;cin>>z>>x>>y;
		if(z==1){
			//合并
			int fx=find(x);
			int fy=find(y);
			fa[fx]=fy;
		}else{
			//查询 
			int fx=find(x);
			int fy=find(y);
			if(fx==fy) cout<<"Y"<<endl;
			else cout<<"N"<<endl;
		}
	}
	return 0;
}

种类并查集

扩展域并查集 可描述敌对关系

敌人 朋友 没关系 扩展为2n

天敌 同类 猎物 没关系 扩展为3n

P1525 [NOIP 2010 提高组 关押罪犯 - 洛谷](https://www.luogu.com.cn/problem/P1525)

C++ 复制代码
#include <bits/stdc++.h>
using ll=long long;
using namespace std;
const int N=2e4+2; 

int f[2*N];
struct enemy{
	int a,b,c;
}e[100005];

bool cmp(enemy& e1,enemy& e2){
	return e1.c>e2.c; 
}

int find(int x){
	if(f[x]==x){
		return x;
	}
	else return f[x]=find(f[x]);
}

int main(){
	int n,m;cin>>n>>m;
	for(int i=1;i<=2*n;++i){
		f[i]=i;
	}
	for(int i=1;i<=m;++i){
		cin>>e[i].a>>e[i].b>>e[i].c;
	}
	sort(e+1,e+m+1,cmp);
	for(int i=1;i<=m;i++){
		int fa=find(e[i].a);
		int fb=find(e[i].b); 
		int fad=find(e[i].a+n);
		int fbd=find(e[i].b+n);
		if(fa==fb){
			cout<<e[i].c;
			return 0;
		}
		f[fa]=fbd;
		f[fb]=fad;
	}
	cout<<0<<endl;
	return 0;
}

P2024 [NOI2001 食物链 - 洛谷](https://www.luogu.com.cn/problem/P2024)

C++ 复制代码
#include <bits/stdc++.h>
using ll=long long;
using namespace std;
const int N=5e4+5; 

int f[3*N];

int find(int x){
	if(f[x]==x){
		return x;
	}
	else return f[x]=find(f[x]);
}

int main(){
	int n,k;cin>>n>>k;
	int ans=0;
	for(int i=1;i<=3*n;++i){
		f[i]=i;
	} 
	while(k--){
		int m,x,y;
		cin>>m>>x>>y;
		if(x>n||y>n||(m==2&&x==y)){
			ans++;
			continue;
		}
		int fx=find(x);//x同类 
		int fy=find(y);//y同类 
		int xenemy=find(x+n);//x天敌 
		int yenemy=find(y+n);//y天敌 
		int xeat=find(x+2*n);//x猎物 
		int yeat=find(y+2*n);//y猎物 
		if(m==1){
			if(xenemy==fy||yenemy==fx){
				ans++;
			}else{
				f[fx]=fy;
				f[xenemy]=yenemy;
				f[xeat]=yeat;		
			}
		}
		if(m==2){
			if(fx==fy||yeat==fx){
				ans++;	
			}else{
				f[fy]=xeat;
				f[yeat]=xenemy;
				f[yenemy]=fx;
			} 
		}
	}
	cout<<ans; 
	return 0;
}
相关推荐
小小龙学IT21 分钟前
ZeroMQ(libzmq)开源消息库深度解析:brokerless 时代的轻量消息内核
c++·开源
Rambo.xia42 分钟前
为什么去马赛克算法,决定了ISP的画质上限
算法·接口隔离原则
Benny_Tang1 小时前
题解:P10230 [COCI 2023/2024 #4] Lepeze
c++·算法
Geek-Chow1 小时前
06 训练管线:数据如何变成权重
人工智能·算法
我变成萤火虫2 小时前
反悔贪心(经典题目讲解)
c++·算法·贪心算法·stl·排序算法·反悔贪心
_Narcissus_2 小时前
排序算法总结表格
c语言·数据结构·c++·笔记·算法·排序算法·总结
一只小小的芙厨3 小时前
前缀和与差分
数据结构·算法
船厂电气自动化ai大模型3 小时前
AI大模型与数学第42课:泰勒级数完整展开(神经网络近似核心)
人工智能·python·深度学习·算法·机器学习
从琳开始9893 小时前
优选算法——双指针(算法原理+力扣题)
算法·leetcode·职场和发展