一、题目链接
二、题目分析
(一)算法标签
并查集
(二)解题思路
并查集:
- 将两个集合合并
- 询问两个元素是否在同一集合当中
基本原理:
每个集合用一颗树来表示。树根的编号就是整个集合的编号。每个节点存储它的父节点,p[x]表示x的父节点。
问题一:如何判断树根:if(p[x] == x)
问题二:如何求x的集合编号:while(p[x]!=x) x = p[x];
问题三:如何合并两个集合:px是x的集合编号,py是y的集合编号。p[px]=py
核心代码:
初始化
for (int i = 1; i <= n; i ++ ) p[i] = i; // 初始化
int find(int x) // 返回x的祖宗结点 + 路径压缩
int find(int x) // 返回x的祖宗结点 + 路径压缩
{
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
合并两个集合
p[find(a)] = find(b); // 合并操作
判断是否在同一集合中
find(a) == find(b) // 判断是否在同一集合中
三、AC代码
解法一:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e5 + 10;
int n, m;
char op[2];
int a, b;
int p[N];
int find(int x) // 返回x的祖宗结点 + 路径压缩
{
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i ++ ) p[i] = i; // 初始化
while (m -- )
{
scanf("%s%d%d", op, &a, &b);
if (*op == 'M') p[find(a)] = find(b); // 合并操作
else
{
if (find(a) == find(b)) puts("Yes"); // 判断是否在同一集合中
else puts("No");
}
}
return 0;
}