并查集-亲戚

题目背景

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

题目描述

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

输入格式

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

以下 m 行:每行两个数 Mi,Mj,1 <= Mi,Mj<= n,表示 Mi 和 Mj 具有亲戚关系。

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

输出格式

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

代码示例

#include<iostream>
using namespace std;

const int N = 5000 + 10;  // 预留足够大的空间

int p[N];  // p[i]表示i的父节点
int n, m, q;  // n:人数, m:亲戚关系数, q:查询对数

// 查找函数,带路径压缩
int find(int x) {
    if (p[x] != x) {
        p[x] = find(p[x]);  // 路径压缩
    }
    return p[x];
}


int main() {
    // 输入人数、亲戚关系数和查询对数
    cin >> n >> m >> q;

    // 初始化并查集,每个人的父节点是自己
    for (int i = 1; i <= n; i++) {
        p[i] = i;
    }

    // 处理亲戚关系
    while (m--) {
        int x, y;
        cin >> x >> y;
        p[find(x)]=find(y);  // 合并这两个人到同一个集合
    }

    // 处理查询
    while (q--) {
        int z, h;
        cin >> z >> h;
        if (find(z) == find(h)) {
            cout << "Yes" << endl;  // 如果z和h有相同的根节点,则说明有亲戚关系
        } else {
            cout << "No" << endl;   // 否则没有亲戚关系
        }
    }

    return 0;
}
posted @ 2024-11-25 20:17  洋洋萱  阅读(16)  评论(0)    收藏  举报