题意

P1024

简化题意:给定 \(n\) 和 \(k(n\leqslant5\times10^4,k\leqslant10^5)\) ,表示有 \(n\) 个动物, \(k\) 个描述,其中:

\(n\) 个动物分别属于 \(A,B,C\) 中的一种,定义如 \(C\to B\to A\to C\) 的环形食物链;

\(k\) 个描述分两种:1.1 x y表示 \(x,y\) 是同类; 2. 2 x y表示 \(y\to x\) .

在 \(k\) 个描述中,有真假之分,其中假的满足:

  • 与之前的真话矛盾;
  • \(x\) 或 \(y\) 比 \(n\) 大;
  • 同类相吃。

求出假话总数。

思路

思路启发

首先进来一组 \(x,y\) ,易得有且仅有三种有用的关系:

  • \(y\) 是 \(x\) 的同类。
  • \(y\to x\) , \(y\) 是 \(x\) 的猎物;
  • \(y\to x\) , \(x\) 是 \(y\) 的天敌。(其实是与关系1是相互的)

那么,我们要维护三个逻辑关系,即有联通性,又有对立性,就要开 三元种类并查集 了。

实际上就是把一个并查集扩大三倍,在每个并查集里维护联通性,即同类关系;在三个并查集之间维护对立性,即猎物和天敌关系。

实际利用

我们可以假设:(\(B\to A\to C\to B\) ,满足题干关系就行)

  • 集合\(A(1\sim n)\) 为中间者;
  • 集合\(B(n+1\sim 2n)\) 为猎物;
  • 集合\(C(2n+1\sim 3n)\) 为天敌;

现在的目的就是用三个集合,依次维护正确的逻辑关系,如果有假话,那么应无法在上面成立,统计无法成立的关系即可。

不妨用图模拟个样例:

点击查看样例
4 5
1 1 3
2 2 4
2 3 2
1 1 4
2 2 1

\(k_1:\) \(1\) 和 \(3\) 是同类,那么就把它俩合并到一个集合,同时注意到,都在集合\(A\) 中,则分别都会在集合\(B\) 和集合\(C\) 中,它俩同类,那它俩的猎物和天敌必定同类。

\(k_2:\) \(2\) 吃 \(4\) ,则有两个逻辑关系:

  • \(4\) 是 \(2\) 的猎物,此时 \(2\) 是中间者,在集合\(A\) ,\(4\) 是猎物,在集合\(B\) ,即 \(4(B)\to2(A)\) ;
  • \(2\) 是 \(4\) 的天敌,此时 \(4\) 是中间者,在集合\(A\) ,\(2\) 是天敌,在集合\(C\) ,即 \(4(A)\to2(C)\) ;

但我们观察 \(B\to^1 A\to^2 C\to^3 B\) ,关系 \(3\) 也应存在才能形成循环,即 \(4(C)\to2(B)\) ;

\(k_3:\) 同理。

\(k_4:\) 此时 \(1\) 与 \(4\) 是同类的是假的。

判断同类是否为假,即判断是否存在 \(1\to4\) 或 \(4\to1\) 的情况,即 \(4\) 的猎物是否是 \(1\) 或 \(4\) 的天敌是否是 \(1\) 。(判断有多样,这样统一了左边的 \(1\))

我们非别求一下对应点的根节点看看:

\(k_5:\) 此时 \(2\) 吃 \(1\) 是假的。

判断吃与被吃是否为假,即判断是否存在 \(2\) 与 \(1\) 是同类或 \(2\to1\) 的情况,即 \(2\) 和 \(1\) 是否在同一集合(此时三个集合显然是等效的)或 \(1\) 的猎物是否是 \(2\) 。

code

#include<bits/stdc++.h>
using namespace std;
const int N=5e4+10,K=1e5+10;
int n,k,fa[3*N],cnt;
int get(int x)
{
if(fa[x]==x) return x;
return fa[x]=get(fa[x]);
}
void merge(int x,int y)
{
fa[get(x)]=get(y);
}
int main()
{
cin>>n>>k;
for(int i=1;i<=3*n;i++) fa[i]=i;
for(int i=1;i<=k;i++)
{
int op,x,y;
cin>>op>>x>>y;
if(x>n || y>n) { cnt++; continue; }
if(op==1)
{
if(get(x)==get(y+n) || get(x)==get(y+2*n)) cnt++;
else
{
merge(x,y);
merge(x+n,y+n);
merge(x+2*n,y+2*n);
}
}
else
{
if(get(x)==get(y) || get(x)==get(y+n)) cnt++;
else
{
merge(x,y+2*n);
merge(x+n,y);
merge(x+2*n,y+n);
}
}
}
cout<<cnt<<endl;
return 0;
}

总结

种类并查集不仅可以维护联通性,也可以维护对立性。

P1024 [NOI2001] 食物链【种类并查集】的更多相关文章

  1. P2024 [NOI2001]食物链(种类并查集)

    题目链接: https://www.luogu.org/problemnew/show/P2024 题目描述 动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形.A 吃 B,B 吃 ...

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

    食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 65430   Accepted: 19283 Description ...

  3. POJ1182 食物链 —— 种类并查集

    题目链接:http://poj.org/problem?id=1182 食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: ...

  4. 【题解】P2024 [NOI2001]食物链 - 数据结构 - 并查集

    P2024 [NOI2001]食物链 声明:本博客所有题解都参照了网络资料或其他博客,仅为博主想加深理解而写,如有疑问欢迎与博主讨论✧。٩(ˊᗜˋ)و✧*。 题目描述 动物王国中有三类动物 \(A,B ...

  5. [NOI2001] 食物链 (扩展域并查集)

    题目描述 动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形.A 吃 B,B 吃 C,C 吃 A. 现有 N 个动物,以 1 - N 编号.每个动物都是 A,B,C 中的一种,但是我 ...

  6. [NOI2001]食物链(并查集拓展域)&& [HAOI2006]旅行(Kruskal)

    题目描述 动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形.A 吃 B,B 吃 C,C 吃 A. 现有 N 个动物,以 1 - N 编号.每个动物都是 A,B,C 中的一种,但是我 ...

  7. POJ 1182 食物链(种类并查集)

    记得第一次做这道题的时候,推关系感觉有点复杂,而且写完代码后一直WA,始终找不出错误. 在A了十几道并查集后,再做这道题,发现太小儿科了.发现原来之所以WA,就在于查找根节点时,没有同步更新子节点相对 ...

  8. 洛谷 P2024 [NOI2001]食物链 (并查集)

    嗯... 题目链接:https://www.luogu.org/problemnew/show/P2024 这道题和团伙这道题的思想比较类似,都是一个数组分成几个集合,但这道题的思路更加混乱,建议没做 ...

  9. P2024 [NOI2001]食物链[扩展域并查集]

    大水题一道啊,几分钟切掉. 还是扩展域,每个点拆3个点,之间连边表示有关系(即捕食关系).然后随便判定一下就好了,不难,毕竟NOI上古题目. #include<iostream> #inc ...

  10. 洛谷 P2024 [NOI2001]食物链(种类并查集,加权并查集)

    传送门 解题思路 加权并查集: 什么是加权并查集? 就是记录着每个节点到它的父亲的信息(权值等). 难点:在路径压缩和合并节点时把本节点到父亲的权值转化为到根节点的权值 怎么转化呢? 每道题都不一样Q ...

随机推荐

  1. 谣言检测()《Data Fusion Oriented Graph Convolution Network Model for Rumor Detection》

    论文信息 论文标题:Data Fusion Oriented Graph Convolution Network Model for Rumor Detection论文作者:Erxue Min, Yu ...

  2. C++ 右值引用与一级指针

    将右值引用用于一级指针,在初始化时等号右边必须为右值,有以下几种用法: //方式一:引用一级指针,常规用法 int a = 5; int * &&rrpa = &a; //右值 ...

  3. Failed to convert from type [java.lang.String] to type [java.util.Date] for value '2020-02-06'; nested exception is java.lang.IllegalArgumentException]解决

    今天做springbook项目前端输入日期传到数据库保存报了一下错误 Whitelabel Error Page This application has no explicit mapping fo ...

  4. String 定义一个字符串

    String 定义一个字符串,要用双引号,多个字符串用+号连接 String S = "sjosajojoaf"; System.out.println(S);

  5. CompareTest

    一.说明:Java中的对象,正常情况下,只能进行比较:== 或 != .不能使用 > 或 < 的 但是在开发场景中,我们需要对多个对象进行排序,言外之意,就需要比较对象的大小. 如何实现? ...

  6. 基于tauri+vue3.x多开窗口|Tauri创建多窗体实践

    最近一种在捣鼓 Tauri 集成 Vue3 技术开发桌面端应用实践,tauri 实现创建多窗口,窗口之间通讯功能. 开始正文之前,先来了解下 tauri 结合 vue3.js 快速创建项目. taur ...

  7. JUC(7)四大函数式接口

    文章目录 1.四大函数式接口(必须掌握) 1.1 function 1.2 Predicate 1.3 Consumer 1.4 Supplier 1.四大函数式接口(必须掌握) 1.lambda表达 ...

  8. TensorFlow?PyTorch?Paddle?AI工具库生态之争:ONNX将一统天下

    作者:韩信子@ShowMeAI 深度学习实战系列:https://www.showmeai.tech/tutorials/42 本文地址:https://www.showmeai.tech/artic ...

  9. Redisson源码解读-公平锁

    前言 我在上一篇文章聊了Redisson的可重入锁,这次继续来聊聊Redisson的公平锁.下面是官方原话: 它保证了当多个Redisson客户端线程同时请求加锁时,优先分配给先发出请求的线程.所有请 ...

  10. 从0到1搭建redis6.0.7

    redis集群搭建 一.安装redis 源码安装: 1.下载源码包: wget http://download.redis.io/releases/redis-6.0.7.tar.gz 2.解压到指定 ...