P1551 亲戚——并查集【模板】

题目背景

若某个家族人员过于庞大,要判断两个是否是亲戚,确实还很不容易,现在给出某个亲戚关系图,求任意给出的两个人是否具有亲戚关系。

题目描述

规定:\(x\)\(y\) 是亲戚,\(y\)\(z\) 是亲戚,那么 \(x\)\(z\) 也是亲戚。如果 \(x\)\(y\) 是亲戚,那么 \(x\) 的亲戚都是 \(y\) 的亲戚,\(y\) 的亲戚也都是 \(x\) 的亲戚。

输入格式

第一行:三个整数 \(n,m,p\),(\(n,m,p \le 5000\)),分别表示有 \(n\) 个人,\(m\) 个亲戚关系,询问 \(p\) 对亲戚关系。

以下 \(m\) 行:每行两个数 \(M_i\)\(M_j\)\(1 \le M_i,~M_j\le n\),表示 \(M_i\)\(M_j\) 具有亲戚关系。

接下来 \(p\) 行:每行两个数 \(P_i,P_j\),询问 \(P_i\)\(P_j\) 是否具有亲戚关系。

输出格式

\(p\) 行,每行一个 YesNo。表示第 \(i\) 个询问的答案为“具有”或“不具有”亲戚关系。

输入输出样例 #1

输入 #1

6 5 3
1 2
1 5
3 4
5 2
1 3
1 4
2 3
5 6

输出 #1

Yes
Yes
No

题解

这是一个典型的并查集应用问题,我们可以使用并查集来解决判断两个人是否为亲戚的问题。以下是使用 C++ 实现的代码:

#include <iostream>
#include <vector>
using namespace std;
class UnionFind {
private:
vector<int> parent;
public:
UnionFind(int n) {
parent.resize(n + 1);
for (int i = 1; i <= n; ++i) {
parent[i] = i;
}
}
int find(int x) {
if (parent[x] != x) {
parent[x] = find(parent[x]);
}
return parent[x];
}
void unionSet(int x, int y) {
int rootX = find(x);
int rootY = find(y);
if (rootX != rootY) {
parent[rootX] = rootY;
}
}
bool isConnected(int x, int y) {
return find(x) == find(y);
}
};
int main() {
int n, m, p;
cin >> n >> m >> p;
UnionFind uf(n);
// 处理亲戚关系,进行合并操作
for (int i = 0; i < m; ++i) {
int Mi, Mj;
cin >> Mi >> Mj;
uf.unionSet(Mi, Mj);
}
// 处理询问
for (int i = 0; i < p; ++i) {
int Pi, Pj;
cin >> Pi >> Pj;
if (uf.isConnected(Pi, Pj)) {
cout << "Yes" << endl;
} else {
cout << "No" << endl;
}
}
return 0;
}

代码解释:

  1. 并查集类 UnionFind
    • 构造函数 UnionFind(int n):初始化并查集,将每个人的父节点设为自身,范围从 1n
    • 查找函数 find(int x):使用路径压缩的方式查找元素 x 的根节点。
    • 合并函数 unionSet(int x, int y):将 xy 所在的集合合并。
    • 判断连通性函数 isConnected(int x, int y):判断 xy 是否在同一个集合中,即是否为亲戚。
  2. 主函数 main()
    • 读取输入的人数 n、亲戚关系数量 m 和询问数量 p
    • 创建并查集对象 uf
    • 读取 m 个亲戚关系,调用 unionSet 函数将对应的两人所在集合合并。
    • 读取 p 个询问,调用 isConnected 函数判断两人是否为亲戚,并输出相应结果。

复杂度分析:

  • 时间复杂度:初始化并查集的时间复杂度为 ,每次合并和查找操作的平均时间复杂度接近 ,因此总的时间复杂度为 。
  • 空间复杂度:主要用于存储并查集的 parent 数组,空间复杂度为 。
发布于   xiins  阅读(5)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示