BZOJ 1370: [Baltic2003]Gang团伙(luogu 1892)(种类并查集)

题面:

  bzoj题面有误,还是看luogu的吧

  https://www.luogu.org/problemnew/show/P1892

题解:

  种类并查集。。

  因为有敌人的敌人是朋友这个条件,所以需要一个中转点。。

  因此,将每个点拆成两个点,一个是朋友点,另一个是敌人点。当读到A与B是朋友时,就将A与B所对应的朋友点并集;当读到两个点是敌人的时候,就将A点所对应的敌人点与B所对应的朋友点并集,将A所对应的朋友点和B所对应的敌人点并集。

代码:

#include<bits/stdc++.h>

using namespace std;

const int maxn=3010;
int fa[maxn],n,m,x,y,vis[maxn],ans;
char ch[3];

int ffa(int x){
    return fa[x]==x?x:fa[x]=ffa(fa[x]);
}

int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=2*n;i++) fa[i]=i;
    for(int i=1;i<=m;i++){
        scanf("%s%d%d",ch,&x,&y);
        if(ch[0]==‘F‘){
            int fx=ffa(x),fy=ffa(y);
            if(fx!=fy) fa[fy]=fx;
        }
        else{
            int fx=ffa(x),fy=ffa(y);
            int fxx=ffa(x+n),fyy=ffa(y+n);
            if(fx!=fyy) fa[fyy]=fx;
            if(fxx!=fy) fa[fxx]=fy;
        }
    }
    for(int i=1;i<=n;i++)
        if(!vis[ffa(i)])
            ans++,vis[ffa(i)]=1;
    printf("%d",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/tang666/p/8761484.html

时间: 2024-08-02 16:03:14

BZOJ 1370: [Baltic2003]Gang团伙(luogu 1892)(种类并查集)的相关文章

BZOJ 1370 Baltic2003 Gang团伙 并查集

题目大意:给定n个人,朋友的朋友是朋友,敌人的敌人是朋友,朋友之间组成一个团伙,求团伙数 将每个点x拆成两个:x和x+n 如果x和y是朋友,就将x和y合并 如果x和y是敌人,就将x和y+n合并,将y和x+n合并 注意敌人的朋友不一定是敌人,因此如果x和y是朋友,不能将x+n和y+n合并 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M

BZOJ 4195: [Noi2015]程序自动分析 [并查集 离散化 | 种类并查集WA]

题意: 给出若干相等和不等关系,判断是否可行 woc NOI考这么傻逼的题飞快打了一个种类并查集交上了然后爆零... 发现相等和不等看错了异或一下再叫woc90分 然后发现md$a \neq b, a \neq c,不能得到b = c$ 老老实实的把所有相等关系加并查集然后不等关系来判断吧,唉 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using

POJ1703--Find them, Catch them(种类并查集)

Time Limit: 1000MSMemory Limit: 10000K Total Submissions: 32909Accepted: 10158 Description The police office in Tadu City decides to say ends to the chaos, as launch actions to root up the TWO gangs in the city, Gang Dragon and Gang Snake. However, t

Poj(1703),种类并查集

题目链接:http://poj.org/problem?id=1703 已经不是第一次接触种类并查集了,直到今天才搞懂. 感谢红黑联盟,感谢杰哥!!! 每个节点只要关系确定,不管是不是同一个集合里面,都把他们放到一个集合里面,用一个rank[]数组记录他们与根节点的关系,比较神奇的地方有两处: 1.find函数里面,因为find是递归写的,不断往上找,不断更新rank[x](与根节点的关系),这个%k,也是很牛逼的,2种类型,标号只有01: 2.Union函数里面,更新rank[fy],rank

NOI2001|POJ1182食物链[种类并查集 向量]

食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 65430   Accepted: 19283 Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用两种说法对这N个动物所构成的食物链关系进行描述: 第一种说法是"1 X Y",表示X和Y是同

种类并查集,Poj(1703)

题目链接:http://poj.org/problem?id=1703 第一次做种类并查集,有的地方还不是很清楚,想了一上午,有点明白了,这里记录一下. 这里我参考的红黑联盟的题解. 关键:种类并查集与带权并查集实质上的差别并不大, 关键的区别就是种类并查集只是带权并查集再弄个%取余操作而已,然后余数就表示他属于哪个种类. rank数组表示节点和父节点的关系(也可以理解为他的种类). find中,找到x的父节点后,那么更新他与父节点的关系,rank[x] = (rank[x]+rank[fa])

[poj1703]Find them, Catch them(种类并查集)

题意:食物链的弱化版本 解题关键:种类并查集,注意向量的合成. $rank$为1代表与父亲对立,$rank$为0代表与父亲同类. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<cmath> using namespace std; typedef long long ll; #de

poj 2492 a bug&#39;s life 简单种类并查集

题意大致为找同性恋的虫子.... 这个比食物链要简单些.思路完全一致,利用取余操作实现关系之间的递推. 个人感觉利用向量,模和投影可能可以实现具有更加复杂关系的并查集. 1 #include<cstdio> 2 using namespace std; 3 const int MAXN=50010; 4 int fa[MAXN]; 5 int rel[MAXN]; // 0代表同类,1代表吃fa[i],2代表被吃 6 void _set(int n) 7 { 8 for(int i=1;i&l

POJ1182 食物链---(经典种类并查集)

题目链接:http://poj.org/problem?id=1182 食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 69207   Accepted: 20462 Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用两种说法对这N个动物所构成的食