C/C++数据结构--并查集-洛谷-P3367 【模板】并查集

并查集是一种树型的数据结构,用于处理一些不交集(Disjoint Sets)的合并及查询问题。有一个联合-查找算法union-find algorithm)定义了两个用于此数据结构的操作:

Find:确定元素属于哪一个子集。它可以被用来确定两个元素是否属于同一子集。

Union:将两个子集合并成同一个集合。

在一个并查集中,我们采用每个集合选一个特定的元素,做为整个集合的代表。

用一棵树的结构来维护一个集合,树根就是这个集合的代表元素。

每个节点有一个父节点,数组fa[i]存i的父亲,树根的父亲为自己。

 

基本操作:

find(x)  查询x所在集合的代表元素(树根)

find(x)== find(y)判断两个集合是否属于同一集合

fa[find(x)] = find(y)      合并两个集合

 

路径压缩

一条链的长度影响查找速度;然而并查集只关心根节点(代表元素),而不关注树的形态

 

洛谷题目

题目描述

如题,现在有一个并查集,你需要完成合并和查询操作。

输入格式

第一行包含两个整数 N,MN,M ,表示共有 NN 个元素和 MM 个操作。

接下来 MM 行,每行包含三个整数 Z_i,X_i,Y_iZi​,Xi​,Yi​ 。

当 Z_i=1Zi​=1 时,将 X_iXi​ 与 Y_iYi​ 所在的集合合并。

当 Z_i=2Zi​=2 时,输出 X_iXi​ 与 Y_iYi​ 是否在同一集合内,是的输出 Y ;否则输出 N 。

输出格式

对于每一个 Z_i=2Zi​=2 的操作,都有一行输出,每行包含一个大写字母,为 Y 或者 N 。

输入输出样例

输入 #1复制

4 7
2 1 2
1 1 2
2 1 2
1 3 4
2 1 4
1 2 3
2 1 4

输出 #1复制

N
Y
N
Y

说明/提示

对于 30\%30% 的数据,N \le 10N≤10,M \le 20M≤20 。

对于 70\%70% 的数据,N \le 100N≤100,M \le 10^3M≤103 。

对于 100\%100% 的数据,1\le N \le 10^41≤N≤104,1\le M \le 2\times 10^51≤M≤2×105 。

 

#include 
#include 
using namespace std;

const int MAX_SIZE = 10001;
int fa[MAX_SIZE];

// 初始化,父节点是本身
void init(int maxSize)
{
    for(int i = 0; i < maxSize; i++)
    {
        fa[i] = i;
    }
}

// 查找代表元素,(根节点)
int find(const int x)
{
    // 父节点是本身即根节点
    if(fa[x] == x)
    {
        return x;
    }

    // find(fa[x]) 递归找根节点
    // fa[x] = find(fa[x]) 压缩路径,当前节点的父节点等于当前节点的父节点的根节点
    return fa[x] = find(fa[x]);
}

// 是否属于同一个集合
bool comp(const int x, const int y)
{
    return find(x) == find(y);
}

// 合并元素 x根节点的父节点等于y的根节点
void merge(const int x, const int y)
{
    fa[find(x)] = find(y);
}

int main()
{
    int n,m;
    cin >> n >> m;

    init(MAX_SIZE);
    int z,x,y;
    while(m--)
    {
        scanf("%d%d%d",&z,&x,&y);
        if(z == 1)
        {
            merge(x, y);
        }
        else if(z == 2)
        {
           cout << (comp(x, y) ? "Y" : "N") << endl;
        }
    }

    return 0;
}

C/C++数据结构--并查集-洛谷-P3367 【模板】并查集_第1张图片

你可能感兴趣的:(C/C++程序)