题干:
一共有 nn 个数,编号是 1∼n1∼n,最开始每个数各自在一个集合中。
现在要进行 mm 个操作,操作共有两种:
M a b
,将编号为 aa 和 bb 的两个数所在的集合合并,如果两个数已经在同一个集合中,则忽略这个操作;Q a b
,询问编号为 aa 和 bb 的两个数是否在同一个集合中;
输入格式
第一行输入整数 nn 和 mm。
接下来 mm 行,每行包含一个操作指令,指令为 M a b
或 Q a b
中的一种。
输出格式
对于每个询问指令 Q a b
,都要输出一个结果,如果 aa 和 bb 在同一集合内,则输出 Yes
,否则输出 No
。
每个结果占一行。
数据范围
1≤n,m≤1051≤n,m≤105
输入样例:
4 5
M 1 2
M 3 4
Q 1 2
Q 1 3
Q 3 4
输出样例:
Yes
No
Yes
代码:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100010;
int p[N];//存放代表元素
//查找 x 所属的集合,就是 x 元素的代表元素
int find(int x)
{
//如果 x 的代表元素不是他自己,就递归的x的代表元素修改为代表元素的代表元素
if(x != p[x]) p[x] = find(p[x]);
return p[x];
}
//合并a b所在的两个集合
void merge(int a, int b)
{
int pa = find(a);//找到 a 所在集合的代表元素
int pb = find(b);//找到 b 所在集合的代表元素
if(pa != pb)//如果不是同一个,则属于不同集合,需要合并
{
p[pa] = pb;//将a所在集合代表元素的代表元素设置为b所在集合的代表元素。
}
}
void query(int a,int b)
{
int pa = find(a);//找到 a 所在集合的代表元素
int pb = find(b);//找到 b 所在集合的代表元素
//判断 a 和 b 是否有同一个代表元素
if(pa == pb) cout << "Yes" << endl;
else cout << "No" << endl;
return ;
}
int main()
{
int n, m;
cin >> n >> m;
//初始化代表元素集合,开始的时候,各自属于一个集合,即每个元素的代表元素是他自己。
for (int i = 1; i <= n; i ++ )
p[i] = i;
while (m -- )
{
char op;
cin >> op;
int a, b;
cin >> a >> b;
if(op == 'M')
{//合并
merge(a, b);
}
else
{//查询
query(a, b);
}
}
}