朴素并查集

 并查集(又加找父亲 hh)

 并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常在使用中以森林来表示。集就是让每个元素构成一个单元素的集合,并就是按一定顺序将属于同一组的元素所在的集合合并。

 并查集的基本操作:

 1.初始化,使每个节点的祖宗节点为自己。

 2.将两个集合合并成一个集合。

 3.查找两个元素是否在一个集合。

  最关键的就是find函数:

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

find函数是用来寻找每个节点的祖宗节点是哪个 以当前的节点的集合开始寻找,如果自身不是祖宗节点,则询问父亲节点,直到寻找到祖宗节点并且回溯将每个节点全部连接到祖宗节点,即使祖宗节点成为其父亲节点。


 

一共有n个数,编号是1~n,最开始每个数各自在一个集合中。

现在要进行m个操作,操作共有两种:

  1. “M a b”,将编号为a和b的两个数所在的集合合并,如果两个数已经在同一个集合中,则忽略这个操作;
  2. “Q a b”,询问编号为a和b的两个数是否在同一个集合中;

输入格式

第一行输入整数n和m。

接下来m行,每行包含一个操作指令,指令为“M a b”或“Q a b”中的一种。

输出格式

对于每个询问指令”Q a b”,都要输出一个结果,如果a和b在同一集合内,则输出“Yes”,否则输出“No”。

每个结果占一行。


 

  上代码:

 1 #include<iostream>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 int a,b;
 6 int f[100010];
 7 int find(int x)
 8 {
 9     if(f[x]!=x) f[x]=find(f[x]);
10     return f[x];
11 }
12 int main()
13 {
14     int n,m;
15     cin>>n>>m;
16     for(int i=1;i<=n;i++) f[i]=i;//初始化,使每个节点的祖宗节点是自己 
17     char str[2];
18     while(m--)
19     {
20         scanf("%s%d%d",str,&a,&b);
21         //使a的父亲节点变成b的祖宗节点,即使两个集合合并成一个集合
22         if(str[0]=='M') f[find(a)]=find(b);
23         else 
24         {
25             if(find(a)==find(b)) cout<<"Yes"<<endl;
26             //如果a的祖宗节点等于b的祖宗节点,那么说明a,b在同一个集合 
27             else cout<<"No"<<endl;
28         }
29     }
30 }

 

posted @ 2020-11-05 02:04  筱翼深凉  阅读(134)  评论(0编辑  收藏  举报