一般我们的并查集是可以维护这样的关系的,比如亲戚的亲戚是亲戚,只需要简单调用并查集就可以实现。但如果我们现在想要维护一个这样的关系,比如敌人的敌人是朋友,那一般的并查集就不行了,对于一般的并查集而言,它只能维护敌人的敌人是敌人,或者是朋友的朋友是朋友,对于敌人的敌人是朋友这种关系是无法维护的,那么为了解决这种问题,就引出了种类并查集去解决这个问题。
例题:洛谷P2024

链接: https://www.luogu.com.cn/problem/P2024

动物王国中有三类动物 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 句话有的是真的,有的是假的。当一句话满足下列三条之一时,这句话就是假话,否则就是真话。
当前的话与前面的某些真的话冲突,就是假话
当前的话中 X 或 Y 比 N 大,就是假话
当前的话表示 X 吃 X,就是假话
你的任务是根据给定的 N 和 K 句话,输出假话的总数。
输入格式
第一行两个整数,N,K,表示有 N 个动物,K 句话。
第二行开始每行一句话(按照题目要求,见样例)
输出格式
一行,一个整数,表示假话的总数。
输入输出样例
输入 #1
100 7
1 101 1
2 1 2
2 2 3
2 3 3
1 1 3
2 3 1
1 5 5
输出 #1复制
3
说明/提示
1 ≤ N ≤ 5 ∗ 104
1 ≤ K ≤ 105
对于动物 x 和 y,我们可能有 x 吃 y,x 与 y 同类,x 被 y 吃。但由于关系还是明显的,1 倍大小、2 倍大小的并查集都不能满足需求,3 倍大小不就行了!类似上面,我们将并查集分为 3 个部分,每个部分代表着一种动物种类。设我们有 n 个动物,开了 3n 大小的种类并查集,其中1∼n 的部分为 A 群系,n+1∼2n 的部分为 B 群系,2n+1∼3n 的部分为 C 群系。我们可以认为 A 表示中立者,B 表示生产者,C 表示消费者。此时关系明显:A 吃 B,A 被 C 吃。当然,我们也可以认为 B 是中立者,这样 C 就成为了生产者,A 就表示消费者。但仍然注意了!我们不知道某个动物属于 A,B,还是 C,我们 3 个种类都要试试!也就是说,每当有 1 句真话时,我们需要合并 3 组元素。容易忽略的是,题目中指出若 x 吃 y,y 吃 z,应有 x 被 z 吃。若将 x 看作属于 A,则 y 属于 B,z 属于 C。最后,根据关系 A 被 C 吃可得 x 被 z 吃。
举个栗子:
设有四个动物,1是2的天敌(√),1和4是同类(√),1和2是同类(×),1和2是天敌(×),先设初始的并查集为(1 - 4表示四个群系,5 - 8表示猎物,9 ~ 12表示天敌):

(1)若1吃了2,并查集维护之后为(2就要连1的猎物,1就要连2的天敌):

(2)若1和4是同类(那么1和4就要连线,推出1和4的猎物也是同类,连线,1和4的天敌也是同类,连线)

(3)现在给出了1和2是同类,显然与前面相悖,那么我们怎么根据以已经画号图来判断呢,我们通过推理可以知道,如果1不是2的猎物,2也不是1的猎物,那1和2肯定是同类,因此我们可以通过判断1+4和2是否在一个集合,2+4和1是否在一个集合去判断它是否成立。即1的猎物集合有没有2,2的猎物集合有没有1,如果它们之中有一个条件成立了,显然1和2就不是同类,如果都不成立,那么1和2就是同类
(4)现在再给出2吃了1,也是一个错误的信息。那么同上,我们怎么用画好的图就判断它们是否在一个集合中呢,如果1和2不是同类且1不吃2,那么显然2吃1是成立的,所以我们要根据图判断一下,1和2是否在一个集合中,1+4是否和2在一个集合中,如果上面两个条件都不成立,那么1吃2成立,如果上面两个条件有一个成立了,那么1吃2不成立。

注意事项
种类并查集求的并非具体种类,而是关系!
在代码过程中,不要忘了特判编号大于 n 的情况!
就这个题而言需要用scanf和printf或者用写快读函数,用cin和cout会TLE!
本人写的是按秩合优化的并查集,正常的并查集模板也是可以的!

并查集模板:

void init()//初始化
{for(int i=0;i<MAXN;i++){parent[i]=i;}
}
int find_root(int t)//查询代表元
{int root=t;while(parent[root]!=root)root=parent[root];while(parent[t]!=root){int tmp=parent[t];parent[t]=root;t=tmp;}return root;
}void union_root(int a,int b)//合并
{int a_root=find_root(a);int b_root=find_root(b);if(a_root==b_root)return ;else{parent[b_root]=a_root;}return ;
}

按秩合优化的写法为(judge数组用来记录树的高度):

void init()//初始化
{for(int i=0;i<MAXN;i++){parent[i]=i;judge[i]=0;}
}
int find_root(int t)//查询代表元
{int root=t;while(parent[root]!=root)root=parent[root];return root;
}void union_root(int a,int b)//合并
{int a_root=find_root(a);int b_root=find_root(b);if(a_root==b_root)return ;if(judge[a_root]==judge[b_root]){parent[b_root]=a_root;judge[a_root]++;}else if(judge[a_root]>judge[b_root])parent[b_root]=a_root;else parent[a_root]=b_root;return ;
}

下面附此题AC代码:

#include<iostream>
#include<memory.h>
#include<math.h>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
const int MAXN=50000*3+10;
int parent[MAXN];
int judge[MAXN];
int n,k,d,x,y;void init()
{for(int i=0;i<MAXN;i++){parent[i]=i;judge[i]=0;}
}
int find_root(int t)
{int root=t;while(parent[root]!=root)root=parent[root];return root;
}void union_root(int a,int b)
{int a_root=find_root(a);int b_root=find_root(b);if(a_root==b_root)return ;if(judge[a_root]==judge[b_root]){parent[b_root]=a_root;judge[a_root]++;}else if(judge[a_root]>judge[b_root])parent[b_root]=a_root;else parent[a_root]=b_root;return ;
}int main()
{int sum=0;init();scanf("%d%d",&n,&k);for(int i=0;i<k;i++){scanf("%d%d%d",&d,&x,&y);if(x>n||y>n){sum++;continue;}if(d==1){if(find_root(x)==find_root(y+n)||find_root(y)==find_root(x+n)){sum++;}else{union_root(x,y);union_root(x+n,y+n);union_root(x+2*n,y+2*n);}}else if(d==2){if(x==y){sum++;continue;}if(find_root(x)==find_root(y)||find_root(x)==find_root(y+n)){sum++;}else{union_root(x,y+2*n);union_root(y,x+n);union_root(y+n,x+2*n);}}}printf("%d\n",sum);return 0;
}

食物链(种类并查集)相关推荐

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

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

  2. 食物链 (种类并查集)

    文章目录 食物链 思路 AC代码 食物链 题目描述 动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形.A 吃 B,B 吃 C,C 吃 A. 现有 N 个动物,以 1 - N 编号. ...

  3. POJ1182 食物链---(经典种类并查集)

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

  4. 【POJ - 1703】Find them, Catch them(带权并查集之--种类并查集 权为与父节点关系)

    题干: Find them, Catch them Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 36176   Accep ...

  5. Bailian1182 POJ1182 食物链【并查集】

    1182:食物链 描述 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到 ...

  6. 【C语言】算法学习·种类并查集

    一般的并查集,维护的是具有连通性.传递性的关系,例如亲戚的亲戚是亲戚.但是,有时候,我们要维护另一种关系:敌人的敌人是朋友.种类并查集就是为了解决这个问题而诞生的. 我们先来看一个例题: 其实很容易想 ...

  7. Poj(1703),种类并查集

    题目链接:http://poj.org/problem?id=1703 已经不是第一次接触种类并查集了,直到今天才搞懂. 感谢红黑联盟,感谢杰哥!!! 每个节点只要关系确定,不管是不是同一个集合里面, ...

  8. BZOJ 1370: [Baltic2003]Gang团伙 [并查集 拆点 | 种类并查集WA]

    题意: 朋友的朋友是朋友,敌人的敌人是朋友:朋友形成团伙,求最多有多少团伙 种类并查集WA了一节课,原因是,只有那两种关系才成立,诸如朋友的敌人是朋友之类的都不成立! 所以拆点做吧 #include ...

  9. poj 1703(种类并查集)

    题目大意:在这个城市里有两个黑帮团伙,现在给出N个人,问任意两个人他们是否在同一个团伙 输入D x y代表x于y不在一个团伙里 输入A x y要输出x与y是否在同一团伙或者不确定他们在同一个团伙里 解 ...

最新文章

  1. 你说,一个Java字符串到底有多少个字符?
  2. LeetCode 报错解决 heap-buffer-overflow Heap-use-after-free Stack-buffer-overflow Global-buffer-overflow
  3. python实现将文件内容按照某一列内容的大小值重新排序_Python数据分析入门教程(四):数值操作...
  4. 如何洞察行业中的应用场景?(上篇)
  5. Java应用程序中的消息传递主体
  6. 【转】SASS用法指南
  7. C 语言调用CPU指令,CPU 1214C中 TSEND_C指令 最多可以使用几次-工业支持中心-西门子中国...
  8. python 编程模型
  9. 记录一次linux病毒清除过程
  10. React 开发常见报错解决方法
  11. jQuery学习(十二)—jQuery中对象的查找方法总结
  12. 美英澳联合发布2020-2021期间遭利用最多的 Top 30漏洞
  13. 大学生考华为认证有用吗?考研还是考证?这些困扰你许久的问题终于搞明白了
  14. css折叠样式(4)——div+css布局
  15. Nuage:如何看待SD-WAN battle升级
  16. VC++域名转IP(网络直接连接域名)
  17. ORACLE和MYSQL一些函数和实现效果的对比、替换
  18. JavaWeb项目-快递代领-需求分析(二)-软件工程-小组项目
  19. python网络爬虫学习的汇总
  20. 关于印发《留学回国人员申办上海常住户口实施细则》的通知

热门文章

  1. php 将pdf生成图片,php 将pdf转成图片且将图片拼接
  2. 圣诞节!教你用 Python 画棵圣诞树
  3. 剑指Offer——编程题的Java实现
  4. React-Native 知识点小结
  5. 苹果怎么关闭自动更新系统_iPhone系统关闭自动更新教程
  6. 【附源码】计算机毕业设计SSM校园流浪猫关爱系统
  7. structure-from-motion revisited论文笔记
  8. 使用ardunio制作神秘礼物(环境光传感器、舵机、LED、蜂鸣器)
  9. 移动手机用户目录下的证书至根目录下
  10. 线段树版子题【HDU - 1166 敌兵布阵】【HDU-1754 I Hate It】【HDU-1698 Just a Hook】【OpenJ_Bailian3439A Simple Pro】