这就是并查集的模板
主函数之前 int一个 f [ 只要不爆,想开多少开多少 ]个元素
然后编写一个查询操作 int find (int i ) { return f[i] == i ? i : find ( f[i] ) ; }
一开始要有一步的初始化即 for(int i=1;i<=n;++i) f[i]=i;//使一开始自己的老大就是自己;
然后进行读入操作,读入a,b两个元素,然后将a,b合并(合并操作find函数),简单来说就是a,b两个人在社会上混的太孤独了,所以两个人合并了,结合在一起,毕竟团结就是力量
两种优化并查集的操作
1、按秩合并(是一个我不大用的操作)
说的通俗一点呢,就是A团体和B团体(用小写字母表示一个元素,用大写字母表示一个集合)两个集合在合并时,由于*不大相同,所以就把*小的(内部元素少的)的老大定为原先*大的老大,这样两个团体就完成合并了;
2、路径压缩(下面的代码就是路径压缩&&我以后的大部分并查集的使用)
说的通俗一点呢,路径压缩就是在一个元素(可能是一个集合的老大)进入当前集合时,直接安排在 并列第二 的位置上,不管怎么样,先插入再说。
下面是路径压缩的代码
int find (int i) { return f[i] == i ? i : f[i] = find ( f[i] ) ; }
在读入循环里for里
{//输入的是a,b
int x = find( f[a] ) , y = find ( f[b] ) ; f[x] = y ;
}//这就行了;
3、可能还有,只是我太 “ 蒻 ” 了!超出我的认知范围了。
下面是本题代码!!!
#include <iostream>
#include <cstdio>
using namespace std;
int n,m,f[10086];
int find(int x){
if(f[x]==x)return x;
return f[x]=find(f[x]);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){f[i]=i;}
for(int i=0;i<m;i++){
int x,y,z;
scanf("%d%d%d",&z,&x,&y);
if(z==1)
f[find(x)]=find(y);
if(z==2)
if(find(x)==find(y))
printf("Y\n");
else
printf("N\n");
}
return 0;
}
附上几道题 方便以后练习
https://www.luogu.org/problemnew/show/P1551 普及- 亲戚。
https://www.luogu.org/problemnew/show/P1536 普及/提高- 村村通
https://www.luogu.org/problemnew/show/P1547 普及/提高- Out of Hay
https://www.luogu.org/problemnew/show/P2078 普及/提高- 朋友
https://www.luogu.org/problemnew/show/P1195 普及+/提高 口袋的天空
都是一些很好的板子题目,裸的并查集,忘了可以看一看。