【Luogu P2024&P1892】食物链&团伙(并查集拓展域)

Luogu P1892
Luogu P2024
这两道一眼看过去很容易发现可以用并查集来做——但是当我们仔细阅读题面后,会发现其实并没有那么简单。
我们知道并查集可以很轻松地维护具有传递性的信息,也就是“朋友的朋友就是我的朋友”这样的关系,但是普通的并查集并不能维护“敌人的敌人是朋友”这种关系。
这时候我们就要引入一种神奇的操作,将并查集扩大一倍,将增加的这一倍空间来维护节点i的敌人。
例如对于团伙这一题

    if (c=='F')
        {
            merge(x,y);
        }
        else
        {
            merge(x,y+n);
            merge(y,x+n);
            //x+n代表的是x的敌人集合
        }

非常好理解,确实是一种相当高效的操作。

P1892完整代码

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=2001;
int fa[maxn],n,m,cnt,x,y;
int getf(int v)
{
    if (fa[v]==v) return fa[v];
    return fa[v]=getf(fa[v]);
}
inline void merge(int x,int y)
{
    fa[getf(y)]=getf(x);
}
inline bool check(int x,int y)
{
    if (getf(x)==getf(y)) return true;
    return false;
}
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++)
    {
        char c;
        scanf("\n%c %d %d",&c,&x,&y);
        if (c=='F')
        {
            merge(x,y);
            //merge(x+n,y+n);
            //注意上面这句不能要,因为题目中没有说到朋友的敌人也是我的敌人。
        }
        else
        {
            merge(x,y+n);
            merge(y,x+n);
        }
    }
    for (int i=1;i<=n;i++) fa[i]=getf(i);//路径压缩,防止压缩不完全
    for (int i=1;i<=n;i++) if (fa[i]==i) cnt++;
    printf("%d\n",cnt);
    return 0;
}

P2024完整代码

#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=3*5*1e4+10;
int fa[maxn],cnt,n,k,flag,x,y;
int getf(int v)
{
    if (fa[v]==v) return v;
    return fa[v]=getf(fa[v]);
}
inline void merge(int x,int y)
{
    x=getf(x);
    y=getf(y);
    fa[x]=y;
}
inline bool check(int x,int y)
{
    x=getf(x);
    y=getf(y);
    if (fa[x]==fa[y]) return true;
    return false;
}
int main()
{
    scanf("%d%d",&n,&k);
    for (int i=1;i<=3*n;i++)
        fa[i]=i;
    //i+n是i吃的集合,i+2n是吃i的集合
    for (int i=1;i<=k;i++)
    {
        scanf("%d%d%d",&flag,&x,&y);
        if (x>n||y>n) {cnt++;continue;}
        if (flag==1)
        {
            if (check(x+n,y)) {cnt++;continue;}
            if (check(x+2*n,y)) {cnt++;continue;}
            merge(x,y);
            merge(x+n,y+n);
            merge(x+2*n,y+2*n);
        }
        if (flag==2)
        {
            if (check(x,y)) {cnt++;continue;}
            if (check(y+n,x)) {cnt++;continue;}
            merge(x+n,y);
            merge(y+2*n,x);
            merge(x+2*n,y+n);
        }
    }
    printf("%d\n",cnt);
    return 0;
}

原文地址:https://www.cnblogs.com/notscience/p/11828321.html

时间: 2024-12-13 17:52:44

【Luogu P2024&P1892】食物链&团伙(并查集拓展域)的相关文章

P1892 [BOI2003]团伙 并查集

题目描述 1920年的芝加哥,出现了一群强盗.如果两个强盗遇上了,那么他们要么是朋友,要么是敌人.而且有一点是肯定的,就是: 我朋友的朋友是我的朋友: 我敌人的敌人也是我的朋友. 两个强盗是同一团伙的条件是当且仅当他们是朋友.现在给你一些关于强盗们的信息,问你最多有多少个强盗团伙. 输入输出格式 输入格式: 输入文件gangs.in的第一行是一个整数N(2<=N<=1000),表示强盗的个数(从1编号到N). 第二行M(1<=M<=5000),表示关于强盗的信息条数. 以下M行,每

POJ1182 食物链 【并查集变种】

挺简单的 N个元素扩展为 3*N个 i-A i-B i-C A吃B吃C吃A 挑战程序设计的89面 #include <cstdio> #include <cstdlib> #include <iostream> #include <cstring> #include <cmath> using namespace std; int N,K; const int MAX_N=333333; //并查集 int par[MAX_N]; int ran

poj 1182 食物链 种类并查集

食物链是并查集的进阶运用的一道非常经典的题目. 题目如下: 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用两种说法对这N个动物所构成的食物链关系进行描述: 第一种说法是"1 X Y",表示X和Y是同类. 第二种说法是"2 X Y",表示X吃Y. 此人对N个动物,用上述两种说法,一句接一句地说出K句话,这K句话有的是真的

POJ 1182 食物链【并查集】

题目链接:http://poj.org/problem?id=1182 此题利用并查集解决. 对于每只动物i创建3个元素i-A,i-B,i-C,并用这3*N个元素建立并查集. 1·i-x表示"i属于种类x" 2·并查集你的每一组表示组内所有元素代表的情况同时发生或不发生. 对于每一条信息,只需要按照下列操作即可: 1.第一种:x,y同类,合并x-A和y-A.x-B和y-B.x-C和y-C. 2.第二种:x吃y,,,合并x-A和y-B.x-B和y-C.x-C和y-A. 当然,在合并之前,

poj 1182:食物链(并查集,食物链问题)

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

poj2492 A Bug&#39;s Life (并查集拓展)

C - A Bug's Life Crawling in process... Crawling failed Time Limit:10000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 2492 Appoint description: CSUST_11 (2013-04-14) System Crawler (2016-05-13) Description B

poj 2492 A Bug&#39;s Life 【并查集拓展】

A Bug's Life Time Limit: 10000MS   Memory Limit: 65536K Total Submissions: 29030   Accepted: 9455 Description Background Professor Hopper is researching the sexual behavior of a rare species of bugs. He assumes that they feature two different genders

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> u

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是同