AcWing 836.合并集合(并查集)

题目


(并查集好像面试挺爱考的,代码短还有思维)


思路
  • AcWing 836.合并集合(并查集)_第1张图片

if (p[a] != a) p[a] = find(p[a]);

  • 判断2个数是否属于同一个集合,只需要判断其根节点是否一样
  • 如果递归求根节点,会很慢,所以涉及了并查集的优化,如果不是根节点的话,可以直接一步求出根节点`
  • 也就是把 a节点所在的树的根节点的值赋给 a所在树的根节点,就是找到a所在树的根节点

p[find(a)] = find(b)

  • 表示, 将b节点所在的树连接在以a节点所在的树上

代码
#include 
using namespace std;

const int N = 1e5 + 10;
int p[N]; // 当前节点的父节点;

// 该函数的含义:查找a所在集合的祖先节点下标,从1开始, 并内部更新p[a]为a节点的祖先节点。
int find(int a)
{
    // 根据通项公式,假设p[a]的祖先节点已知。
    if (p[a] != a) p[a] = find(p[a]);
    return p[a];
}

int main()
{
    int n, m;
    scanf("%d %d", &n, &m);

    // 初始化每个集合
    for (int i = 1; i <= n; i++) p[i] = i;

    int a, b;
    char op[2];
    while (m--)
    {
        scanf("%s%d%d", op, &a, &b);
        if (op[0] == 'M') p[find(a)] = find(b);
        else {
            if (find(a) == find(b)) puts("Yes");
            else puts("No");
        }
    }
    return 0;
}


你可能感兴趣的:(练习题)