题目链接:https://cn.vjudge.net/problem/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句话有的是真的,有的是假的。当一句话满足下列三条之一时,这句话就是假话,否则就是真话。

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

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

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

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

思路

思路有二

  1. 把某一动物转化为三个并查集

    一个集合为同类,一个是食物,一个是天敌

    这样来说更容易管理,也就更好写

    插入数据

    按照同类食物和天敌的集合合并即可

    注意a+n代表a元素的敌人;a+2×n代表a元素的食物

    find(a)find(b+n)意思是b的敌人在a的集合里 -> a类是b的敌人

    find(a+n)find(b+2*n)意思是b的食物在a敌人的集合里 -> a的敌人类是b的食物类

    检查数据

    然而这样来说内存就是一个大问题了

    现在来算一下吧,最大内存问题

\[Mem = 3*2*N*4 = 1.2e6 B = 1.2e3 kB < 1e4 kB
\]

看来没什么问题,一开始忘了算了,直接去了思路二,痛苦不堪

2. 一个动物是一个并查集

把根节点做一个标志,标志比其他的大就算是捕食者,取模即可

然而不好写,半途改变思想了

代码

#include <cstdio>
const int MAX=int(5e4);
struct Node{
int parent, rank;
Node(int parent=0, int rank=1):
parent(parent),rank(rank) {}
}node[3*MAX+5];
int find(int x){
return (x==node[x].parent)?x:(node[x].parent=find(node[x].parent));
} void join(int a, int b){
a=find(a); b=find(b);
if (a==b) return;
if (node[a].rank==node[b].rank) node[a].rank++;
if (node[a].rank>node[b].rank) node[b].parent=a;
else node[a].parent=b;
} int main(void){
int ans=0, n, m, oper[3]; scanf("%d%d", &n, &m);
for (int i=1; i<=3*n; i++) node[i]=Node(i);
for (int snt=0; snt<m; snt++){
scanf("%d%d%d", &oper[0], &oper[1], &oper[2]);
if (oper[1]>n || oper[2]>n) {ans++; continue;}
if (oper[0]==2 && oper[1]==oper[2]) {ans++; continue;} // self-0*n, eater-1*n, food-2*n
if (oper[0]==1){
// if (vis[oper[1]] && vis[oper[2]] && find(oper[1])!=find(oper[2])) {ans++; continue;}
if (find(oper[1])==find(oper[2]+n) || find(oper[1])==find(oper[2]+2*n)){ans++; continue;}
join(oper[1], oper[2]);
join(oper[1]+n, oper[2]+n);
join(oper[1]+2*n, oper[2]+2*n);
}else if (oper[0]==2){
if (find(oper[1])==find(oper[2]) || find(oper[1])==find(oper[2]+2*n)){ans++; continue;}
join(oper[1], oper[2]+n);
join(oper[1]+n, oper[2]+2*n);
join(oper[1]+2*n, oper[2]);
}
}printf("%d\n", ans); return 0;
}
Time Memory Length Lang Submitted
282ms 1528kB 1489 G++ 2018-02-16 16:28:58

> 03-18 Update: 又写了一边题,发现并没有理解解法。重新思考,把要点详细说明一下

POJ-1182 食物链 并查集(互相关联的并查集写法)的更多相关文章

  1. poj 1182 食物链 &amp;&amp; nyoj 207(种类并查集)

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

  2. poj 1182 食物链 (带关系的并查集)

      食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 44835 Accepted: 13069 Description 动 ...

  3. poj 1182:食物链(种类并查集,食物链问题)

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

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

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

  5. POJ 1182 食物链 [并查集 带权并查集 开拓思路]

    传送门 P - 食物链 Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u Submit  ...

  6. poj 1182 食物链 并查集 题解《挑战程序设计竞赛》

    地址 http://poj.org/problem?id=1182 题解 可以考虑使用并查集解决 但是并不是简单的记录是否同一组的这般使用 每个动物都有三个并查集 自己 天敌 捕食 并查集 那么在获得 ...

  7. POJ 1182 食物链(经典带权并查集 向量思维模式 很重要)

    传送门: http://poj.org/problem?id=1182 食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: ...

  8. POJ 1182——食物链——————【种类并查集】

    食物链 Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u Submit Status P ...

  9. POJ 1182 食物链

    G - 食物链 Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u Submit Stat ...

  10. poj 1182 食物链 (并查集)

    http://poj.org/problem?id=1182 关于并查集 很好的一道题,开始也看了一直没懂.这次是因为<挑战程序设计竞赛>书上有讲解看了几遍终于懂了.是一种很好的思路,跟网 ...

随机推荐

  1. Synergy 共享键盘和鼠标

    直接安装Synergy 不行的话加配置文件 ➜ ~ cat synergy.conf section: screens lab712-PC: ckboss-HP: end section: links ...

  2. TYVJ 1541 八数码

    Orz双向搜索的cy大神 我用的是hash 也蛮快的 //By SiriusRen #include <queue> #include <cstdio> using names ...

  3. vim编辑器常用语法

    1)yy (功能描述:复制光标当前一行) y数字y (功能描述:复制一段(从第几行到第几行))2)p (功能描述:箭头移动到目的行粘贴)3)u (功能描述:撤销上一步)4)dd (功能描述:删除光标当 ...

  4. 51nod 1649 齐头并进 (djikstra求最短路径,只用跑一次)

    题目: 这道题有一个坑点:两种交通工具同时出发,中途不能停留在同一个小镇. 其实想通了就很简单,因为要么火车一步到达,要么汽车一步到达.不可能停留在同一个地方. 可是我还WA了好几次,蠢哭.想用BFS ...

  5. row_number函数的使用

    转 row_number函数的使用 SQL Server数据库ROW_NUMBER()函数的使用是本文我们要介绍的内容,接下来我们就通过几个实例来一一介绍ROW_NUMBER()函数的使用. 实例如下 ...

  6. python面向对象的成员、属性等

    #类成员: #字段 self.xy =qq . xy=qq #普通字段 (保存在对象里面) #直接通过点(.)+ 字段 进行调用 #静态字段 (保存在类里面) #静态字段属于类,在内存只保留一份 . ...

  7. mongodb报错:connection refused because too many open connections: 819

    问题: 发现mongodb无法连接,查看mongodb日志,出现大量的如下报错: [initandlisten] connection refused because too many open co ...

  8. H3C S5130交换机堆叠操作

    配置过程中注意事项: 1.最好提前定义好IRF的主从设备,可通过IRF优先级进行定义,越大越优 2.一定要在使能IRF之前就保存配置(因为使能过程中,会出现设备重启的情况,如果设备重启后配置丢失,会导 ...

  9. OpenJDK源码研究笔记(五)-缓存Integer等类型的频繁使用的数据和对象,大幅度提升性能(一道经典的Java笔试题)

    摘要 本文先给出一个看似很简单实则有深意的Java笔试面试题,引出JDK内部的缓存. JDK内部的缓存,主要是为了提高Java程序的性能. 你能答对这道"看似简单,实则有深意"的J ...

  10. HDU——T 2444 The Accomodation of Students

    http://acm.hdu.edu.cn/showproblem.php?pid=2444 Time Limit: 5000/1000 MS (Java/Others)    Memory Limi ...