亲戚
题目背景
若某个家族人员过于庞大,要判断两个是否是亲戚,确实还很不容易,现在给出某个亲戚关系图,求任意给出的两个人是否具有亲戚关系。
题目描述
规定: 和 是亲戚, 和 是亲戚,那么 和 也是亲戚。如果 , 是亲戚,那么 的亲戚都是 的亲戚, 的亲戚也都是 的亲戚。
输入格式
第一行:三个整数 ,(),分别表示有 个人, 个亲戚关系,询问 对亲戚关系。
以下 行:每行两个数 ,,,表示 和 具有亲戚关系。
接下来 行:每行两个数 ,询问 和 是否具有亲戚关系。
输出格式
行,每行一个 Yes 或 No。表示第 个询问的答案为“具有”或“不具有”亲戚关系。
样例 #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
解题思路
要点: 并查集
:::tip UnionFind 实现
class UnionFind {
vector<int> set_;
public:
explicit UnionFind(const int len): set_(len) {
for (int i = 0; i < len; ++i) {
set_[i] = i;
}
}
int find(int idx) {
if (set_[idx] == idx) {
return idx;
}
else {
set_[idx] = find(set_[idx]); //路径压缩
return set_[idx];
}
// return set_[idx] == idx ? idx : set_[idx] = find(set_[idx]);
}
bool merge(const int va, const int vb){
const int a = find(va - 1);
const int b = find(vb - 1);
if (a == b) {
return false;
}
set_[a] = b;
return true;
}
bool is_connected(const int va, const int vb) {
return find(va - 1) == find(vb - 1);
}
};:::
:::details 输入输出整理
#include <vector>
#include <iostream>
using std::vector;
using std::cout;
using std::cin;
using std::endl;
void print(bool x) {
if (x) {
cout << "Yes" << endl;
}
else {
cout << "No" << endl;
}
}
int main(int argc, char* argv[]) {
int n, m, p;
cin >> n >> m >> p;
auto u = UnionFind(n);
for (int i = 0; i < m; ++i) {
int mi, mj;
cin >> mi >> mj;
u.merge(mi, mj);
}
vector<bool> ans(p);
for (int i = 0; i < p; ++i) {
int pi, pj;
cin >> pi >> pj;
ans[i] = u.is_connected(pi, pj);
}
for (auto an : ans) {
print(an);
}
}
:::
