合并集合(并查集)

并查集

并查集可以快速实现( 时间复杂度近乎 O(1) ):
1.将两个集合合并
2.判断两个元素是否在一个集合中
基本原理:每个集合用一棵树来表示,树根的编号就是这个集合的编号,每个节点存储自身的父节点,用p[x]表示 x 节点的父节点,当p[x]= x时,表示这个结点为根节点。在进行合并操作时,只需要把其中一棵树变成另一棵树的子树即可,即两个树根节点分别是 p[x] =x 和 p[y] =y; 我们只需要将 p[y] =x 即可。

路径压缩优化:在进行结点查找根节点的操作后,直接把这个这个结点的路径上的所有结点的父节点直接指向根节点,下次再查询这些结点时时间复杂度就变成O(1)了。

例题:

image-20250906214753577

输入样例:

4 5
M 1 2
M 3 4 
Q 1 2
Q 1 3
Q 3 4

预期输出:

Yes
No
Yes

代码实现:

#include<bits/stdc++.h>
using namespace std;

const int N =1e5+10;

int p[N];

int find (int x )
{
    if (p[x] != x ) p[x] =find(p[x]); //路径压缩优化,将该路径上的每个结点的父节点都直接指向根节点。下次查询的时候时间复杂度可以优化到O(1)
    return p[x];
}

int main()
{
    for(int i =0;i<N;i++) p[i]=i;
    int n,m;
    bool flag ;
    cin>>n>>m;
    while(m--)
    {
        char op[2];
        int a,b;
        scanf("%s%d%d",op,&a,&b);
        if(op[0] == 'M') p[find(a)] = find(b);//合并:让其中一个结点所在的树变成另一个结点的子树
        else
        {
            if(find(a) == find(b)) cout<<"Yes"<<endl;
            else cout<<"No"<<endl;
        }
    }
}

  

posted @ 2025-09-06 23:15  小花护符  阅读(12)  评论(0)    收藏  举报