朋友

朋友

题目背景

小明在 A 公司工作,小红在 B 公司工作。

题目描述

这两个公司的员工有一个特点:一个公司的员工都是同性。

A 公司有 \(N\) 名员工,其中有 \(P\) 对朋友关系。B 公司有 \(M\) 名员工,其中有 \(Q\) 对朋友关系。朋友的朋友一定还是朋友。

每对朋友关系用两个整数 \((X_i,Y_i)\) 组成,表示朋友的编号分别为 \(X_i,Y_i\)。男人的编号是正数,女人的编号是负数。小明的编号是 \(1\),小红的编号是 \(-1\)

大家都知道,小明和小红是朋友,那么,请你写一个程序求出两公司之间,通过小明和小红认识的人最多一共能配成多少对情侣(包括他们自己)。

输入格式

输入的第一行,包含 \(4\) 个空格隔开的正整数 \(N,M,P,Q\)

之后 \(P\) 行,每行两个正整数 \(X_i,Y_i\)

之后 \(Q\) 行,每行两个负整数 \(X_i,Y_i\)

输出格式

输出一行一个正整数,表示通过小明和小红认识的人最多一共能配成多少对情侣(包括他们自己)。

样例 #1

样例输入 #1

4 3 4 2
1 1
1 2
2 3
1 3
-1 -2
-3 -3

样例输出 #1

2

提示

对于 \(30 \%\) 的数据,\(N,M \le 100\)\(P,Q \le 200\)

对于 \(80 \%\) 的数据,\(N,M \le 4 \times 10^3\)\(P,Q \le 10^4\)

对于 \(100 \%\) 的数据,\(N,M \le 10^4\)\(P,Q \le 2 \times 10^4\)

分析

这道题看似通过建立男女两个并查集,然后再遍历一下个公司员工看他们是否与1有关系,但要注意:女生是负数,所以输入要记得abs,其次,是查找操作,也要对1进行查找,不能直接等于1.

代码实现

#include <bits/stdc++.h>
using namespace std;

const int N = 30000;
int s[N];
int height[N];

void init_set() {
    for (int i = 1; i <= N; i++) {
        s[i] = i;
        height[i] = 0;
    }
}

int find_set(int x) {
    if (x != s[x]) s[x] = find_set(s[x]);
    return s[x];
}

void merge_set(int x, int y) {
    x = find_set(x);
    y = find_set(y);
    if (x == y) return;
    if (height[x] == height[y]) {
        height[x]++;
    }
    if (height[x] < height[y]) {
        s[x] = y;
    } else {
        s[y] = x;
    }
}

int main() {
    int n, m, p, q, nn = 0, mm = 0;
    cin >> n >> m >> p >> q;
    init_set();
    while (p--) {
        int a, b;
        cin >> a >> b;
        merge_set(a, b);
    }
    for (int i = 1; i <= n; i++) {
        if (find_set(i) == find_set(1)) nn++;
    }
    init_set();
    while (q--) {
        int a, b;
        cin >> a >> b;
        a = abs(a);
        b = abs(b);
        merge_set(a, b);
    }
    for (int i = 1; i <= m; i++) {
        if (find_set(i) == find_set(1)) mm++;
    }
    cout << min(nn, mm);
    return 0;
}
posted @ 2023-08-30 20:44  LongDz  阅读(20)  评论(0)    收藏  举报