朋友
题目背景
小明在 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\)。
输出格式
输出一行一个正整数,表示通过小明和小红认识的人最多一共能配成多少对情侣(包括他们自己)。
样例
样例输入
4 3 4 2
1 1
1 2
2 3
1 3
-1 -2
-3 -3
样例输出
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\)
[!TIP]
并查集
#include <bits/stdc++.h>
using namespace std;
const int N = 2e4 + 10;
int n, m, p, q, x, y;
int f[N], g[N];// 查找函数
int find1(int x) {if (f[x] == x) {return x;} else {return f[x] = find1(f[x]);}
}
int find2(int x) {if (g[x] == x) {return x;} else {return g[x] = find2(g[x]);}
}// 合并函数
void baka1(int x, int y) {int findX = find1(x);int findY = find1(y);if (findX != findY) {f[findX] = findY;}
}void baka2(int x, int y) {int findX = find2(x);int findY = find2(y);if (findX != findY) {g[findX] = findY;}
}int main() {scanf("%d %d %d %d", &n, &m, &p, &q);// 初始化for (int i = 1; i <= n; i++) {f[i] = i;}for (int i = 1; i <= m; i++) {g[i] = i;}//合并Afor (int i = 0; i < p; i++) {scanf("%d %d", &x, &y);baka1(x, y);}//合并Bfor (int i = 0; i < q; i++) {scanf("%d %d", &x, &y);baka2(-x, -y); // B公司员工性别为女,编号为负,要取反}}int FFF1 = 0, FFF2 = 0;//FFF是单身狗最后的倔强for (int i = 1; i <= n; i++) {if (find1(i) == find1(1)) {FFF1++;}}for (int i = 1; i <= m; i++) {if (find2(i) == find2(1)) {FFF2++;}}printf("%d\n", min(FFF1, FFF2));return 0;
}
我们也可以通过定义fumo来区分,从而合并find 和 baka
#include <bits/stdc++.h>
using namespace std;
const int N = 2e4 + 10;
int n, m, p, q, x, y;
int f[N], g[N];// 查找函数
int find(int x, int fumo) {if (fumo == 1) {if (f[x] == x) {return x;} else {return f[x] = find(f[x], fumo);}} else if (fumo == 2) {if (g[x] == x) {return x;} else {return g[x] = find(g[x], fumo);}}
}// 合并函数(用fumo区分AB)
void baka(int x, int y, int fumo) {int findX = find(x, fumo);int findY = find(y, fumo);if (findX!= findY) {if (fumo == 1) {//Af[findX] = findY;} else if (fumo == 2) {//Bg[findX] = findY;}}
}int main() {scanf("%d %d %d %d", &n, &m, &p, &q);// 初始化(员工只和自己有朋友关系)for (int i = 1; i <= n; i++) {f[i] = i;}for (int i = 1; i <= m; i++) {g[i] = i;}// 合并Afor (int i = 0; i < p; i++) {scanf("%d %d", &x, &y);baka(x, y, 1);}// 合并Bfor (int i = 0; i < q; i++) {scanf("%d %d", &x, &y);baka(-x, -y, 2); //B公司员工性别为女,编号为负,要取反}// 统计与小明(1)和小红(反1)的朋友关系数量int FFF1 = 0, FFF2 = 0;//定义为FFF是单身狗最后的倔强for (int i = 1; i <= n; i++) {if (find(i, 1) == find(1, 1)) {FFF1++;}}for (int i = 1; i <= m; i++) {if (find(i, 2) == find(1, 2)) {FFF2++;}}printf("%d\n", min(FFF1, FFF2));return 0;
}