今天学习并查集,一种常用的树的算法,之后还会学习哈夫曼树

并查集:利用树型结构来处理一些不相交的集合的合并和查询问题

合并两个集合(两棵树):只需要合并两棵树的根节点,先找到各自的根节点,把根节点设立父子关系即可

查询两个节点是否在同一个集合(树):只需要找到两个节点的根节点,看根节点是否相同

并查集用树型结构实现:双亲表示法

并查集算法优化:路径压缩(递归实现)

例题:洛谷p1551—亲戚

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Tree_Node
{
public:
    int fi;
    int data;
public:
};
class Tree
{
public:
    int size;
    Tree_Node* pN;
public:
    Tree(int sz):size(sz)
    {
        pN = new Tree_Node[sz];
        for (int i = 0; i < sz; ++i)
        {
            pN[i].fi = pN[i].data = i + 1;
        }
    }
    int Find_fi(int k)//找祖先
    {
        while (pN[k - 1].fi != k)
        {
            k = pN[k - 1].fi;
        }
        return k;
    }
    int Find_fi_2(int k)//递归实现,实现路径压缩
    {
        if (pN[k - 1].fi == k)
        {
            return k;
        }
        else
        {
            //实现路径压缩
            pN[k - 1].fi = Find_fi_2(pN[k - 1].fi);//将双亲改为祖先
            return pN[k - 1].fi;
            //也可以写作return pN[k - 1].fi = Find_fi_2(pN[k - 1].fi);
        }
    }
};
int main()
{
    int n(0);
    int m(0);
    int p(0);
    cin >> n >> m >> p;
    Tree tr(n);
    int a(0);
    int b(0);
    int fa(0);
    int fb(0);
    for (int i = 0; i < m; ++i)
    {
        cin >> a >> b;
        fa = tr.Find_fi_2(a);
        fb = tr.Find_fi_2(b);

        tr.pN[fa - 1].fi = fb;
    }
    for (int i = 0; i < p; ++i)
    {
        cin >> a >> b;
        if (tr.Find_fi_2(a) == tr.Find_fi_2(b))
        {
            cout << "Yes" << endl;
        }
        else
        {
            cout << "No" << endl;
        }
    }
    return 0;
}