Luogu P2078 朋友 题解

该博客介绍了一个关于员工配对的问题,其中A公司和B公司的员工分别由男性和女性组成,且各自内部存在朋友关系。小明和小红是跨公司的好友,任务是找出通过他们俩最多能配成多少对情侣。输入包括公司员工数量和朋友关系,程序通过并查集实现求解,并输出最大配对数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目背景

小明在 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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值