P1892 [BOI2003]团伙(并查集,反集)难度⭐⭐★

题目链接
在这里插入图片描述

反集

如果ab是敌人,合并n+ban+ab
如果ca是敌人,合并n+can+ac
那么bc自然就合并在一起了
这样就符合了题目敌人的敌人是朋友的规则

注意

并查集不要忘了初始化

注意

输入的时候scanf要用%s 因为scanf遇见空格是不会跳的,所以尽量这种时候就不要用scanf,比较麻烦,cin它不香嘛

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=1e5+7;
const ll mod=2147483647;
ll n,m;
ll f[N];
inline void init()//并查集必须要初始化!
{
    for(int i=1;i<=(n<<1|1);++i)
        f[i]=i;
}
inline ll finds(ll x)
{
    return f[x]==x?x:f[x]=finds(f[x]);
}
inline void add(ll x,ll y)
{
    x=finds(x);
    y=finds(y);
    f[x]=y;
}
inline bool check(ll x,ll y)
{
    x=finds(x);
    y=finds(y);
    return x==y;
}
int main()
{
    scanf("%lld %lld",&n,&m);
    init();
    for(int i=1;i<=m;++i)
    {
        ll a,b;
        char ch[2];
        scanf("%s%lld%lld",&ch,&a,&b);//注意这一点要用%s 因为scanf遇见空格是不会跳的,所以尽量这种时候就不要用scanf,比较麻烦,cin它不香嘛
        //cin>>ch>>a>>b;
        if(ch[0]=='F')add(a,b);
        else {
            add(a+n,b);//反集
            add(b+n,a);//敌人的敌人就是我的朋友
        }
    }
    ll ans=0;
    for(int i=1;i<=n;++i)//查祖先数
        if(f[i]==i)ans++;
    printf("%lld\n",ans);
    return 0;
}

有任何疑问欢迎评论哦虽然我真的很菜
点个关注再走吧

发布了110 篇原创文章 · 获赞 92 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_45697774/article/details/104824518