一、题目链接
二、题目分析
(一)算法标签
并查集
(二)解题思路
注意本题输入操作不要用char op[3]; + scanf("%s", op); 要用string op; + cin >> op;
初始化:
for (int i = 1; i <= n; i ++ )
{
p[i] = i;
cnt[i] = 1;
}
返回x的祖宗结点:
// 返回x的祖宗结点 + 路径压缩
int find(int x)
{
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
判断a和b是否在同一个集合里面:
// 判断a和b是否在同一个集合里面
bool query(int a, int b)
{
return find(a) == find(b);
}
合并a和b所在的两个集合:
// 合并a和b所在的两个集合,前提是a和b不在一个集合里面,因此在merge之前要判断一下
void merge(int a, int b)
{
a = find(a), b = find(b);
p[a] = b;
cnt[b] += cnt[a];
}
返回a所在连通块(集合)的数量:
// 返回a所在连通块(集合)的数量
int count(int a)
{
return cnt[find(a)];
}
三、AC代码
解法一:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e5 + 10;
int n, m;
int a, b;
string op;
int p[N], cnt[N];
// 返回x的祖宗结点 + 路径压缩
int find(int x)
{
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
// 判断a和b是否在同一个集合里面
bool query(int a, int b)
{
return find(a) == find(b);
}
// 合并a和b所在的两个集合,前提是a和b不在一个集合里面,因此在merge之前要判断一下
void merge(int a, int b)
{
a = find(a), b = find(b);
p[a] = b;
cnt[b] += cnt[a];
}
// 返回a所在连通块(集合)的数量
int count(int a)
{
return cnt[find(a)];
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i ++ )
{
p[i] = i;
cnt[i] = 1;
}
while (m -- )
{
cin >> op;
if (op == "C")
{
scanf("%d%d", &a, &b);
if (!query(a, b)) merge(a, b);
}
else if (op == "Q1")
{
scanf("%d%d", &a, &b);
if (query(a, b)) puts("Yes");
else puts("No");
}
else
{
scanf("%d", &a);
printf("%d\n", count(a));
}
}
return 0;
}