并查集(又加找父亲 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个操作,操作共有两种:
- “M a b”,将编号为a和b的两个数所在的集合合并,如果两个数已经在同一个集合中,则忽略这个操作;
- “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 }