[Luogu] 并查集维护个数 P2078 朋友

本文介绍了一种使用并查集数据结构解决实际问题的方法,针对两个同性别人群构成的公司社交网络,通过维护每个个体所属集合的大小,找出最可能的情侣组合数量。博主通过实例演示了如何运用并查集来简化情侣配对问题,核心在于理解问题的约束条件并巧妙利用数据结构。
摘要由CSDN通过智能技术生成

文章目录

(并查集 维护 集合元素个数 模板题)

题意

两个公司 (全是同性别的人)

也就是一个公司 如果有男生 就不可能有 女生

问你 在 小明(1代表) 和 小红 (-1代表 女生都用负数) 认识的人中

最可能凑出来几对情侣(包括他们自己)

吐槽
本来以为是组合数问题 结果 画了一下关系图 就发现 凑出来的情侣数由 认识少的那一方 限制
(那么问题 就简单了 )

步骤

这不就是 并查集 维护 集合中元素的个数 问题嘛

  • 那我们要怎么 维护 并查集集合中的 个数呢
  • (其实很简单 我们只要加一个 size数组即可 在每次合并的操作的时候 我们直接相加即可)

当然在初始化的时候 每个size[i]都要初始化为1 毕竟 本身也算嘛

if(fa!=fb)
{
    p[fa] = fb;
    sz[fb] +=sz[fa];
}

所以 其他步骤就简单了 就妥妥的 并查集操作即可

CODE

#include <bits/stdc++.h>
#define IOS  ios::sync_with_stdio(false)
using namespace std;
const int N = 4e6+10;
int p[N],pm[N];
int n,m,x,q;
int sz[N],szm[N];

int find(int x)
{
    if(x != p[x])
    return p[x] = find(p[x]);
    return p[x];
}
int findm(int x)
{
    if(x != pm[x])
    return pm[x] = findm(pm[x]);
    return pm[x];
}

void init()
{
    for(int i=1; i<=N; i++)
    {
        p[i]  = i;
        pm[i] = i;
        sz[i] = 1;
        szm[i] = 1;
    }
}
void solve()
{
    cin>>n>>m>>x>>q;
    init();

    for(int i=1; i<=x; i++)
    {
        int a,b;
        cin>>a>>b;
        int fa = find(a);
        int fb = find(b);

        if(fa!=fb)
        {
            p[fa] = fb;
            sz[fb] +=sz[fa];
        }
    }
    for(int i=1; i<=q; i++)
    {
        int a,b;
        cin>>a>>b;
        a=-a, b=-b;
        int fa = findm(a);
        int fb = findm(b);

        if(fa!=fb)
        {
            pm[fa] = fb;
            szm[fb]+=szm[fa];

        }
    }


    int fa = find(1);
    int fb = findm(1);

    int ans = min(sz[fa],szm[fb]);
    cout<<ans<<endl;
}
int main()
{
    IOS;
    solve();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值