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\) 行,每行一个 Yes
或 No
。表示第 \(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; }
代码解释:
- 并查集类
UnionFind
:- 构造函数
UnionFind(int n)
:初始化并查集,将每个人的父节点设为自身,范围从1
到n
。 - 查找函数
find(int x)
:使用路径压缩的方式查找元素x
的根节点。 - 合并函数
unionSet(int x, int y)
:将x
和y
所在的集合合并。 - 判断连通性函数
isConnected(int x, int y)
:判断x
和y
是否在同一个集合中,即是否为亲戚。
- 构造函数
- 主函数
main()
:- 读取输入的人数
n
、亲戚关系数量m
和询问数量p
。 - 创建并查集对象
uf
。 - 读取
m
个亲戚关系,调用unionSet
函数将对应的两人所在集合合并。 - 读取
p
个询问,调用isConnected
函数判断两人是否为亲戚,并输出相应结果。
- 读取输入的人数
复杂度分析:
- 时间复杂度:初始化并查集的时间复杂度为 ,每次合并和查找操作的平均时间复杂度接近 ,因此总的时间复杂度为 。
- 空间复杂度:主要用于存储并查集的
parent
数组,空间复杂度为 。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律