并查集与应用实例

并查集基础知识
观文前,如未了解并查集基础知识请自行学习。

以一道例题来讲
The Number of Imposters

这是CF div2的一道D题,可以用DFS的方法求解,也可以用并查集的方法求解。

题意:a说b是Imposter(骗子),b说c是crewmate(老实人),那么在多组这样的指认关系下,我们能否确定一种骗子最多的情况,如果不能确定输出-1,能的话输出骗子的最大人数

分析可知:对于一组指认关系,如A对B指认。
指认者的身份可以决定被指认者的身份,比如A是老实人的话,那么A说B是什么B就是什么
如果A是骗子,那么B的身份就和A的指认相反。
所以我们可以知道:
1.关键点在于假设指认人的两种身份情况:A(指认人)是骗子和老实人的情况
2.对于这两种情况分别统计确定好的老实人和骗子的数目。
3.利用并查集做统计,1-n表示第一种情况,n+1到2*n表示第二种情况。

分段放置,利于思考

第一段:作为并查集的初始化和统计人数大小数组siz的初始化

        cin>>n>>m;
        for(int i=1;i<=n<<1;i++)
        {
            fa[i]=i;
            siz[i]=(i<=n);//0-n区间为1,n+1到2n区间为0
        }

并查集查找函数:在原本的基础查找函数上,把x所代表的的集合的大小更新。

int find(int x)
{
    if (x == fa[x])
        return x;//对的上根
    fa[x]=find(fa[x]);//对不上根继续找根
    siz[fa[x]]+=siz[x];siz[x]=0;//吧x位置上的所有人放到fa[x]上
    return fa[x];
}

并查集归并函数:基础的归并函数基础上我们根据题意,如果y归并到x的集合内,那么相应的y集合的元素数也加到x集合上,并且y集合清空。

void merge(int x,int y)//把y归并到x上
{
    int fx=find(x),fy=find(y);
    if(fx==fy)
        return;
    siz[fx]+=siz[fy];siz[fy]=0;//把y的成员数量也都给x
    fa[fy]=fx;
}

并查集实现统计:按照分析中的思路,确定了指认关系后,假设指认人的关系。

  for(int i=1,x,y;i<=m;i++)
        {
            cin>>x>>y>>s;
            if (s[0]=='c')
            merge(x,y),merge(x+n,y+n);//诚实则身份与指认同构
            //意思就是:x是老实人的情况下并且指认也是y是老实人(第一种情况),所以把x和y一起归并到老实人的集合,否则(第二种情况)把x和y一起归并到骗子集合
            else
            merge(x,y+n),merge(y,x+n);//不诚实则身份与指认向异
        }

统计答案

 int ans = 0;
        for(int i=1;i<=n;i++)
        {
            if(find(i)==find(i+n))
            {
                ans = -1;
                break;
            } // 一个人在诚实和说谎中都有保留位置,说明矛盾
            ans+=max(siz[find(i)],siz[find(i + n)]);//找到x两种身份情况下最大值
            siz[find(i)]=siz[find(i+n)]=0; //统计过的地方记得清空,为了下次循环使用
        }

输出答案

cout<<ans<<endl;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值