洛谷(LG)P3367【模板】并查集

这就是并查集的模板

主函数之前    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    普及+/提高   口袋的天空

都是一些很好的板子题目,裸的并查集,忘了可以看一看。

上一篇:LG专利新机器人超萌俄罗斯娃娃


下一篇:LG V40 ThinQ大量点!三主镜头与16倍变焦