算法题解—并查集—公司通婚

公司通婚

Description

大连惊现两个很奇葩的互联网公司!
这两个公司(A公司和B公司)的员工有一个特点:一个公司的员工都是同性。
A公司有N名员工,其中有P对朋友关系。B公司有M名员工,其中有Q对朋友关系。朋友的朋友一定还是朋友。
每对朋友关系用两个整数(Xi,Yi)组成,表示朋友的编号分别为Xi,Yi。男人的编号是正数,女人的编号是负数。小邵的编号是1,小刘的编号是-1.
大家都知道,小邵和小刘是朋友,那么,请你写一个程序求出两公司之间,通过小邵和小刘认识的人最多一共能配成多少对情侣。(包括他们自己)

input

第1行,4个空格隔开的正整数N,M,P,Q。
之后P行,每行两个正整数Xi,Yi。
之后Q行,每行两个负整数Xi,Yi。

output

输出一个正整数,表示通过小邵和小刘认识的人最多一共能配成多少对情侣。

Sample Input 1

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

Sample Output

2


题解

该题是一道并查集的题,但是需要稍微修改并查集最后祖先的合并方式。


小邵和小刘的编号为1和-1,所以我们可以对两个公司使用两个并查集。
首先对A公司使用并查集,并查集的最终合并我们取最小的那个为祖先,同理B公司也是,那么最终合并后的结果,我们只需要对每个公司的员工找到其祖先是否为1,如果为1则代表该员工认识一号编号的人。


我们最后计数每个公司的祖先为1的人数,因为题目是问可以凑成多少对,那么我们只需要取两个公司中祖先为1的个数最小的那一个即可。

代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
using namespace std;

const int N = 10010;
int f1[N], f2[N];
int siz1[N], siz2[N];

int n, m, p, q;

int find(int f[],int x) {
	if(f[x] != x) f[x] = find(f,f[x]);
	return f[x];
}

void merge(int f[],int siz[],int a,int b) {
	int t1 = find(f,a);
	int t2 = find(f,b);
	if(t1 != t2) {
		f[t1] = t2;
		siz[t2] += siz[t1];
	}
}

int main()
{
	cin >> n >> m >> p >> q;
	for(int i = 1;i <= n;i ++) {
		f1[i] = i;
		siz1[i] = 1;
	}
	
	for(int i = 1;i <= m;i ++) {
		f2[i] = i;
		siz2[i] = 1;
	}
	
	while(p --) {
		int a, b;
		cin >> a >> b;
		merge(f1,siz1,a,b);
	}
	
	while(q --) {
		int a, b;
		cin >> a >> b;
		merge(f2,siz2,-a,-b);
	}
		
	cout << min(siz1[find(f1,1)],siz2[find(f2,1)]) << endl;
	return 0;
}
```
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值