【题目描述】

动物王国中有三类动物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句话有的是真的,有的是假的。当一句话满足下列三条之一时,这句话就是假话,否则就是真话。

1)当前的话与前面的某些真的话冲突,就是假话;

2)当前的话中X或Y比N大,就是假话;

3)当前的话表示X吃X,就是假话。

你的任务是根据给定的N(1≤ N ≤50,000)和K句话(0≤K≤100,000),输出假话的总数。

【输入】

第一行是两个整数N和K,以一个空格分隔。

以下K行每行是三个正整数 D,X,Y,两数之间用一个空格隔开,其中D表示说法的种类。

若D=1,则表示X和Y是同类。

若D=2,则表示X吃Y。

【输出】

只有一个整数,表示假话的数目。

【输入样例】

100 7
1 101 1
2 1 2
2 2 3
2 3 3
1 1 3
2 3 1
1 5 5

【输出样例】

3


看了不少题解,最终认为下面的这种方法最好理解:

与大多数方法一样,我们并查集空间开3倍大。但关键是后两倍用来表示什么。

这里我引入两个概念,天敌与猎物! 假设x吃y那么y的天敌是x,x的猎物是y。 对于上述的三倍空间,我们分别用其表示:

1–n:表示谁与谁是同类。

n+1–2*n:表示天敌集合。

2*n+1–3*n:表示猎物集合。

那么这是我们再回过头看两种指令:

1.输入x与y,表示x与y为同一种类: 对于x与y,如果他们已经有吃与被吃的关系,则说明为假话。 所以我们检查x与y+n、y+2*n是否在同一集合(y是否为x的猎物或天敌) 如果是则ans++,如果不是则进行合并。 合并时自然三个集合都要合并,即合并: x与y ,x+n与y+n ,x+2*n与y+2*n

2.输入x与y,表示x吃y: 此时如果是假话,那么有两种情况:

- 1.x与y为同一类

- 2.y吃x

对于情况1,我们只需检查x与y是否在一个合集即可。

对于情况2,我们需检查x+n与y是否在同一集合中(x是不是y的猎物)。

如果两种情况都不满足,那么就要连边了。 需要连三条边:

- 1.y+n与x(y是x的猎物)

- 2.x+2*n与y(y的天敌是x)

- 3.x+n与y+2*n(以x的猎物与以y为天敌) - 这里方便理解,可以引入一个动物t - 动物t的猎物是x,由于环状结构,它的天敌一定是y对吧 - 所以x+n与y+2*n本质上是属于一类的,要合并起来!具体实现代码:

 #include<bits/stdc++.h>
using namespace std;
int fa[],ans;
int read()
{
int f=,x=;char s=getchar();
while(s<''||s>''){if(s=='-')f=-;s=getchar();}
while(s>=''&&s<=''){x=x*+s-'';s=getchar();}
x*=f;
return x;
}
void write(int x)
{
if(x<)
{
putchar('-');
x=-x;
}
if(x>)write(x/);
putchar(x%+'');
}
int find(int x)
{
if(fa[x]!=x)fa[x]=find(fa[x]);
return fa[x];
}
int main()
{
int n,m,w,x,y,k,d;
n=read();k=read();
for(int i=;i<=*n;i++)
fa[i]=i;
for(int i=;i<=k;i++)
{
d=read();x=read();y=read();
if(x==y&&d==)
{
ans++;continue;
}
if(x>n||y>n)
{
ans++;continue;
}
if(d==)
{
if(find(x)==find(y+n)||find(x)==find(y+*n))ans++;
else
{
fa[find(y)]=find(x);
fa[find(y+n)]=find(x+n);
fa[find(y+*n)]=find(x+*n);
}
}
if(d==)
{
if(find(x)==find(y)||find(x+n)==find(y)||find(y+*n)==find(x))ans++;
else
{
fa[find(y+n)]=find(x);
fa[find(y)]=find(x+*n);
fa[find(y+*n)]=find(x+n);
}
}
}
write(ans);
return ;
}

//参考:洛谷·P2024 食物链(多条件并查集) - Guess_Ha的博客 - CSDN博客
https://blog.csdn.net/qq_39553725/article/details/76474124

100122212171011231351233315假话真话真话假话假话真话真话100711011假话212真话223真话233假话113假话231真话155真话

食物链【NOI2001】(信息学奥赛一本通 1390)的更多相关文章

  1. $ybt\ 【信息学奥赛一本通】题解目录$

    [信息学奥赛一本通]题解目录 $ \large -> OJ$ $ problem1000 $ \(Answer\) - > $ \large 1000$ $ problem1001 $ \ ...

  2. 2019寒假练题计划——LibreOJ刷题计划 &《信息学奥赛一本通》提高版题目

    目录 2019.1.27 #10082. 「一本通 3.3 例 1」Word Rings 题意 思路 #10083. 「一本通 3.3 例 2」双调路径 题意 思路 #10084. 「一本通 3.3 ...

  3. 【信息学奥赛一本通】第三部分_队列 ex2_3produce 产生数

    给出一个整数n(n<=2000)(代码可适用n<=10^31)和k个变换规则(k<=15). 规则:1.1个数字可以变换成另1个数字: 2.规则中右边的数字不能为零. BFS #in ...

  4. 信息学奥赛一本通算法(C++版)基础算法:高精度计算

    高精度加法(大位相加) #include <bits/stdc++.h> using namespace std; int main() { ],b1[]; ],b[],c[];//a,b ...

  5. Biorhythms(信息学奥赛一本通 1639)

    题目描述: 人生来就有三个生理周期,分别为体力.感情和智力周期,它们的周期长度为23天.28天和33天.每一个周期中有一天是高峰.在高峰这天,人会在相应的方面表现出色.例如,智力周期的高峰,人会思维敏 ...

  6. 信息学奥赛一本通 提高篇 序列第k个数 及 快速幂

    我是传送门 这个题首先是先判断是等差还是等比数列 等差的话非常简单: 前后两个数是等差的,举个栗子: 3 6 9 12 这几个数,(我感觉 1 2 3 4并说明不了什么) 每次都加3嘛,很容易看出,第 ...

  7. 【NOI2002】荒岛野人(信息学奥赛一本通 1637)(洛谷 2421)

    题目描述 克里特岛以野人群居而著称.岛上有排列成环行的M个山洞.这些山洞顺时针编号为1,2,…,M.岛上住着N个野人,一开始依次住在山洞C1,C2,…,CN中,以后每年,第i个野人会沿顺时针向前走Pi ...

  8. X-factor Chain(信息学奥赛一本通 1628)

    题目描述 输入正整数 x,求 x 的大于 1 的因子组成的满足任意前一项都能整除后一项的序列的最大长度,以及满足最大长度的序列的个数. 输入 多组数据,每组数据一行,包含一个正整数 x. 对于全部数据 ...

  9. 【09NOIP提高组】Hankson 的趣味题(信息学奥赛一本通 1856)(洛谷 1072)

    题目描述 Hanks 博士是BT (Bio-Tech,生物技术) 领域的知名专家,他的儿子名叫Hankson.现在,刚刚放学回家的Hankson 正在思考一个有趣的问题.今天在课堂上,老师讲解了如何求 ...

随机推荐

  1. 优先队列 + 模拟 - HDU 5437 Alisha’s Party

    Alisha’s Party Problem's Link Mean: Alisha过生日,有k个朋友来参加聚会,由于空间有限,Alisha每次开门只能让p个人进来,而且带的礼物价值越高就越先进入. ...

  2. 基础知识---IEnumerable、ICollection、IList、IQueryable

    一.定义 IEnumerable public interface IEnumerable<out T> : IEnumerable ICollection public interfac ...

  3. 【spring boot】加载同名Bean解决方法

    原文地址:https://blog.csdn.net/liuyueyi25/article/details/83280239 @SpringBootApplication @ComponentScan ...

  4. CSS实现水平垂直居中的数种方法整合

    CSS实现水平垂直居中可以说是前端老生常谈的问题了,一般面试官问的时候面试者都会回答出来,但是继续追问还有没有其他方法的时候有可能就说不出来了. 本着学习知识的目的,特在此纪录CSS实现水平垂直居中的 ...

  5. python程序设计基础(程序设计基础方法)

    python初学者程序练习题 注:练习题涉及到range()函数的使用方法和python绘制,后面会单独发篇解释说明. 1.字符串拼接.接收用户输入的两个字符串,将它们组合后输出 str1=input ...

  6. ASP.NET MVC IOC 之 Autofac(三)-webform中应用

    在webform中应用autofac,只有global中的写法不一样,其他使用方式都一样 nuget上引用: global中的写法: private void AutoFacRegister() { ...

  7. Java自学-集合框架 与数组的区别

    Java集合框架与数组的区别 示例 1 : 使用数组的局限性 如果要存放多个对象,可以使用数组,但是数组有局限性 比如 声明长度是10的数组 不用的数组就浪费了 超过10的个数,又放不下 //Test ...

  8. mysql的my.cnf

    配置参数详解 [client] #客户端设置,即客户端默认的连接参数port = 3307   #默认连接端口socket = /data/mysqldata/3307/mysql.sock #用于本 ...

  9. Android 培训准备资料之project与module的区别(1)

    project和module的区别? 现在我们来看看在Android studio中怎样新建一个project (1)file->new->new project. Application ...

  10. Android源码分析(十六)----adb shell 命令进行OTA升级

    一: 进入shell命令界面 adb shell 二:创建目录/cache/recovery mkdir /cache/recovery 如果系统中已有此目录,则会提示已存在. 三: 修改文件夹权限 ...