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

并查集

普通并查集

注意根据数据大小来开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;
}
相关推荐
汉克老师5 分钟前
GESP2026年3月认证C++七级( 第三部分编程题(1、物流网络))精讲
c++·最短路·gesp7级
鱼子星_8 分钟前
【C++】深入剖析list:list及其双向迭代器实现
开发语言·数据结构·c++·笔记·stl·list
脚踏实地皮皮晨11 分钟前
003002004_WPF Panel 基类 官方类定义
开发语言·windows·算法·c#·wpf·visual studio
tudousisi22240 分钟前
P4667 [BalticOI 2011] Switch the Lamp On复盘
c++
啊真真真1 小时前
ArgoCD:我的GitOps探索之旅与未来展望
java·算法·argocd
江屿风1 小时前
【C++笔记】【二叉搜索树】流食般投喂
开发语言·数据结构·c++·笔记
海绵天哥2 小时前
LeetCode Hot 100 | 链表(下)· 分组翻转与设计(C++ 题解)
c++·leetcode·链表
choumin2 小时前
行为型模式——中介者模式
c++·设计模式·中介者模式·行为型模式
就改了8 小时前
Java8 日期处理(详细版)
java·python·算法