食物链【NOI2001】(信息学奥赛一本通 1390)
【题目描述】
动物王国中有三类动物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)的更多相关文章
- $ybt\ 【信息学奥赛一本通】题解目录$
[信息学奥赛一本通]题解目录 $ \large -> OJ$ $ problem1000 $ \(Answer\) - > $ \large 1000$ $ problem1001 $ \ ...
- 2019寒假练题计划——LibreOJ刷题计划 &《信息学奥赛一本通》提高版题目
目录 2019.1.27 #10082. 「一本通 3.3 例 1」Word Rings 题意 思路 #10083. 「一本通 3.3 例 2」双调路径 题意 思路 #10084. 「一本通 3.3 ...
- 【信息学奥赛一本通】第三部分_队列 ex2_3produce 产生数
给出一个整数n(n<=2000)(代码可适用n<=10^31)和k个变换规则(k<=15). 规则:1.1个数字可以变换成另1个数字: 2.规则中右边的数字不能为零. BFS #in ...
- 信息学奥赛一本通算法(C++版)基础算法:高精度计算
高精度加法(大位相加) #include <bits/stdc++.h> using namespace std; int main() { ],b1[]; ],b[],c[];//a,b ...
- Biorhythms(信息学奥赛一本通 1639)
题目描述: 人生来就有三个生理周期,分别为体力.感情和智力周期,它们的周期长度为23天.28天和33天.每一个周期中有一天是高峰.在高峰这天,人会在相应的方面表现出色.例如,智力周期的高峰,人会思维敏 ...
- 信息学奥赛一本通 提高篇 序列第k个数 及 快速幂
我是传送门 这个题首先是先判断是等差还是等比数列 等差的话非常简单: 前后两个数是等差的,举个栗子: 3 6 9 12 这几个数,(我感觉 1 2 3 4并说明不了什么) 每次都加3嘛,很容易看出,第 ...
- 【NOI2002】荒岛野人(信息学奥赛一本通 1637)(洛谷 2421)
题目描述 克里特岛以野人群居而著称.岛上有排列成环行的M个山洞.这些山洞顺时针编号为1,2,…,M.岛上住着N个野人,一开始依次住在山洞C1,C2,…,CN中,以后每年,第i个野人会沿顺时针向前走Pi ...
- X-factor Chain(信息学奥赛一本通 1628)
题目描述 输入正整数 x,求 x 的大于 1 的因子组成的满足任意前一项都能整除后一项的序列的最大长度,以及满足最大长度的序列的个数. 输入 多组数据,每组数据一行,包含一个正整数 x. 对于全部数据 ...
- 【09NOIP提高组】Hankson 的趣味题(信息学奥赛一本通 1856)(洛谷 1072)
题目描述 Hanks 博士是BT (Bio-Tech,生物技术) 领域的知名专家,他的儿子名叫Hankson.现在,刚刚放学回家的Hankson 正在思考一个有趣的问题.今天在课堂上,老师讲解了如何求 ...
随机推荐
- 删除链表中的倒数第N个节点
题目 给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点. 示例: 给定一个链表: ->->->->, 和 n = . 当删除了倒数第二个节点后,链表变为 -&g ...
- AtCoder diverta 2019 Programming Contest 2
AtCoder diverta 2019 Programming Contest 2 看起来我也不知道是一个啥比赛. 然后就写写题解QWQ. A - Ball Distribution 有\(n\)个 ...
- 创建Maven项目时,GroupId和Artifact Id该怎么填写呢?
1.什么是groupid和artifactId? groupid和artifactId被统称为“坐标”是为了保证项目唯一性而提出的,如果你要把你项目弄到maven本地仓库去,你想要找到你的项目就必须根 ...
- CSS加载会阻塞页面显示?
可能大家都知道,js执行会阻塞DOM树的解析和渲染,那么css加载会阻塞DOM树的解析和渲染吗?接下来,我们就一起来分析一下. 原理解析 那么为什么会出现上面的现象呢?我们从浏览器的渲染过程来解析下. ...
- C#通过字符串分割字符串Split
string[] strArr = str.Split(new[] {"****==="},StringSplitOptions.None); 更多内容关注公众号 洛水梅家
- sql查询当前数据库的所有表名
SELECT sys.tables.name as TableName from sys.tables
- Linux yum的配置 , python环境管理, nginx搭建简单学习
Linux yum的配置 , python环境管理, nginx搭建简单学习 一丶配置yum的数据仓库 ### yum 工具, 方便,自行解决软件之间的依赖关系. # 配置yum源仓库 (可以使用,清 ...
- javascript format 字符串 函数
函数实现如下: function format(string) { var args = arguments; var pattern = new RegExp("%([1-" + ...
- Vue.js最佳实践--VueRouter的beforeEnter与beforeRouteLeave冲突解决
用Vue做应用管理系统,通常会在离开某个页面的时候,需要检测用户是否有修改,询问用户需要不需要保存之类的需求 这时候,在读VueRouter文档:组件内的守卫 的时候,发现beforeRouteLea ...
- 微信小程序开发--常用开发实例
一.常用商品列表的换行排布 <view class="box_max"> <view class="box_min">限时秒杀</ ...