朋友
題目背景
小明在 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;
}
//合併A
for (int i = 0; i < p; i++) {
scanf("%d %d", &x, &y);
baka1(x, y);
}
//合併B
for (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) {//A
f[findX] = findY;
} else if (fumo == 2) {//B
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;
}
// 合併A
for (int i = 0; i < p; i++)
{
scanf("%d %d", &x, &y);
baka(x, y, 1);
}
// 合併B
for (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;
}