题目背景
小明在 A 公司工作,小红在 B 公司工作。
题目描述
这两个公司的员工有一个特点:一个公司的员工都是同性。
A 公司有 NN 名员工,其中有 P 对朋友关系。B 公司有 M 名员工,其中有 Q 对朋友关系。朋友的朋友一定还是朋友。
每对朋友关系用两个整数(Xi,Yi) 组成,表示朋友的编号分别为Xi,Yi。男人的编号是正数,女人的编号是负数。小明的编号是 1,小红的编号是 −1。
大家都知道,小明和小红是朋友,那么,请你写一个程序求出两公司之间,通过小明和小红认识的人最多一共能配成多少对情侣(包括他们自己)。
输入格式
输入的第一行,包含 44 个空格隔开的正整数 N,M,P,
之后 P 行,每行两个正整数Xi,Yi。
之后 Q 行,每行两个负整数 i,Yi。
输出格式
输出一行一个正整数,表示通过小明和小红认识的人最多一共能配成多少对情侣(包括他们自己)。
输入输出样例
输入 #1
4 3 4 2
1 1
1 2
2 3
1 3
-1 -2
-3 -3
输出 #1
2
说明/提示
对于 100 %的数据,N,M≤10^4,P,Q≤2×10^4。
#include <bits/stdc++.h>
#ifndef ONLINE_JUDGE
#pragma GCC optimize(2)//手工吸氧
//#pragma GCC optimize(3)
#endif
#define INF 0x3f3f3f3f
#define N 100005
#define ll long long
#define ull unsigned long long
#define il inline
#define rg register
using namespace std;
int n, m, p, q;
//并查集类
class ifm
{
int fa[10001];//并查集
int s[10001];//每个集合的大小
public:
//初始化
ifm(int x)
{
//初始状态每个元素的祖先是它自身,所属集合大小为1
for (rg int i = 1; i <= x; i++)
fa[i] = i, s[i] = 1;
}
//查 函数
il int find(int x)
{
//如果祖先是它自己,说明它是这个集合的祖先
if (fa[x] == x)
return x;
return fa[x] = find(fa[x]);//路径压缩
}
//并 函数
il void merge(rg int x,rg int y)
{
x = find(x), y = find(y);//找祖先
if (x != y)
fa[y] = x, s[x] += s[y];
//将y的集合并入x的集合,x所属集合大小加上y所属集合大小
}
//获取集合大小
il int size(rg int x)
{
return s[x];
}
};
int main()
{
cin.sync_with_stdio(false);
cin >> n >> m >> p >> q;
ifm a(n), b(m);//直接传参初始化
rg int x, y;
for (rg int i = 1; i <= p; i++)
{
//A公司信息输入
cin >> x >> y;
a.merge(x, y);
}
for (rg int i = 1; i <= q; i++)
{
//B公司信息输入
cin >> x >> y;
x = abs(x), y = abs(y);//注意B公司员工编号为负,要取绝对值
b.merge(x, y);
}
rg int sa = a.size(a.find(1));//获取小明所在朋友集合的人数
rg int sb = b.size(b.find(1));//获取小红所在朋友集合的人数
//两两配对,则能配成的对数是两个集合中人数少的那个集合的总人数
cout << min(sa, sb) << endl;
system("pause");
return 0;
}