亲戚

题目背景

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

题目描述

规定: 是亲戚, 是亲戚,那么 也是亲戚。如果 是亲戚,那么 的亲戚都是 的亲戚, 的亲戚也都是 的亲戚。

输入格式

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

以下 行:每行两个数 ,表示 具有亲戚关系。

接下来 行:每行两个数 ,询问 是否具有亲戚关系。

输出格式

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

样例 #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);
	}
}
 

:::