• 【题解】P1892 [BOI2003]团伙-C++


    原题传送门
    前置知识:并查集,不会的补了再来。
    这道题只是在并查集的基础上多了一个操作而已。
    这种操作,叫做反集(就先这么叫着)
    题目里有一种关系是互为朋友,这很好理解,把互为朋友的两个点合并就可以了。
    互为敌人怎么办?
    用反集!
    所谓反集,就是分别把x,y和它们对应的虚点连接起来。(虚点:a的虚点是a+n(点数))
    因为一个人不可能和自己是敌人(至少这道题里不会),所以x永远不会和x+n连接起来,但如果x和y+n连接起来了,x和y就永远不会在一个并查集里了。
    有了这个特性,最后检查的时候遍历一遍1-n,如果它是根节点就ans++,最后输出即可。
    代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int n,m,fa[2001],x,y,sz[10001];
     4 char o;
     5 void init()
     6 {
     7     for(int i=1;i<=2000;i++)
     8     {
     9         fa[i]=i;
    10         sz[i]=1;
    11     }
    12 }
    13 int get(int x)
    14 {
    15     if(fa[x]==x)return x;
    16     int r=get(fa[x]);
    17     fa[x]=r;
    18     return r;
    19 }
    20 void merge(int x,int y)
    21 {
    22     int r1=get(x),r2=get(y);
    23     if(r1==r2)
    24     {
    25         return;
    26     }
    27     fa[r1]=r2;
    28     sz[r2]+=sz[r1];
    29     return;
    30 }
    31 int main()
    32 {
    33     cin>>n>>m;
    34     init();
    35     for(int i=1;i<=m;i++)
    36     {
    37         cin>>o>>x>>y;
    38         if(o=='F')merge(x,y);
    39         else 
    40         {
    41             merge(y+n,x);
    42             merge(x+n,y);
    43         }
    44     }
    45     int ans=0;
    46     for(int i=1;i<=n;i++)
    47     {
    48         if(fa[i]==i)ans++;
    49     }
    50     cout<<ans<<endl;
    51     return 0;
    52 }
    个人博客地址: www.moyujiang.com 或 moyujiang.top
  • 相关阅读:
    kubernetes 节点数据彻底清理脚本
    多es 集群数据迁移方案
    .Net Framework各版本微软技术支持及到期日期
    etcd raft 处理流程图系列3-wal的读写
    etcd raft 处理流程图系列2-transport
    etcd raft 处理流程图系列1-raftexample
    一种分布式预写日志系统
    自适应软件缓存管理
    require/import路径中的叹号是什么?
    理解原型链
  • 原文地址:https://www.cnblogs.com/moyujiang/p/11167720.html
Copyright © 2020-2023  润新知