文章目錄
1. 題目描述
1.1. Limit
Time Limit: C/C++ 1秒,其他語言2秒
Memory Limit: C/C++ 65536K,其他語言131072K
1.2. Problem Description
——你要是願意,我就永遠存在某人的朋友圈實在是過於龐大且複雜,要判斷兩個人是不是朋友,那還真不容易。現給出某個朋友圈關係圖,求任意給出的兩個人是否是朋友。規定:如果x和y是朋友,y和z是朋友,那麼x和z也是朋友。如果x和y是朋友,那麼x的朋友都是y的朋友,y的朋友也都是x的朋友。
1.3. Input
第一行,三個整數 ,分別表示有n個人,m個朋友關係,詢問p對朋友關係。
以下m行:每行兩個數,表示 和 具有朋友關係。
接下來 行:每行兩個數 ,詢問 是否具有盆友關係
1.4. Output
行,每行一個“Yes”或“No”(不包含引號)。表示第 個詢問的答案爲“具有”或“不具有”朋友關係。
1.5. Sample Input
6 5 3
1 2
1 5
3 4
5 2
1 3
1 4
2 3
5 6
1.6. Sample Output
Yes
Yes
No
1.7. Source
2. 解讀
使用並查集進行求解。
以如下輸入爲例
6 5 3
1 2
1 5
3 4
5 2
1 3
1 4
2 3
5 6
用 存儲第 個點所在的集團,如圖1所示。
每次查詢,只要判斷其根節點是否相同,即可判斷其是否屬於同一個集團。並且,每次對 進行查詢過後,進行路徑壓縮,也就是將根節點賦值給 ,減少下一次的查詢時間。如圖2所示。
代碼
#include <iostream>
#include <string.h>
using namespace std;
const int num = 5e4 + 1;
int group[num];
int height[num];
// 初始化
void init_set()
{
for (int i = 1; i < num; i++) {
group[i] = i;
// 樹的高度
height[i] = 0;
}
}
// 查找
int find_set(int x)
{
// 路徑壓縮
if (x != group[x]) {
group[x] = find_set(group[x]);
}
return group[x];
}
void union_set(int x, int y)
{
x = find_set(x);
y = find_set(y);
if (height[x] == height[y]) {
// 合併,樹的高度加1
height[x] = height[x] + 1;
group[y] = x;
} else {
// 矮樹合併到高樹上,高樹的高度保持不變
if (height[x] < height[y]) {
group[x] = y;
}else{
group[y] = x;
}
}
}
int main()
{
int n, m, p, x, y;
cin >> n >> m >> p;
// 初始化
init_set();
// 輸入
for (int i = 0; i < m; i++) {
cin >> x >> y;
union_set(x, y);
}
//
for (int i = 0; i < p; i++) {
cin >> x >> y;
if (find_set(x) == find_set(y)) {
cout << "Yes" << endl;
} else {
cout << "No" << endl;
}
}
return 0;
}
聯繫郵箱:[email protected]
CSDN:https://me.csdn.net/qq_41729780
知乎:https://zhuanlan.zhihu.com/c_1225417532351741952
公衆號:複雜網絡與機器學習
歡迎關注/轉載,有問題歡迎通過郵箱交流。