题目大意

动物王国中有三类动物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),输出假话的总数。

题目分析

由于给出X和Y的相对关系,并不能确定X和Y分别是哪种动物,因此没法将动物i属于A、B、C中的哪一类作为一个集合。但是,题目是典型的集合操作,判断两个元素是否符合某种关系,因此仍然考虑使用并查集来解决。
    使用并查集这种结构时候,需要维护相关的数据信息。考虑每两个动物只要能够确定相互关系,则将他们加入一个集合,对于集合中的每个动物,我们维持
该动物和该集合的根节点动物的相对关系。在每次获得两个动物X和Y的相对关系的时候,对于之前已经知道的那些和X或Y相关的动物的关系,只需要知道这些动
物和该共同集合的根节点动物的相对关系,则可以确定他们之间的相对关系。
    在每次得到X和Y之间的关系rel时,先获得他们的根节点,如果根节点p相同,则可以通过X和p的关系,Y和p的关系,确定X和Y在之前就可以确
定的关系rel_1。将rel_1和本次输入的X和Y之间的关系rel进行对比,如果不同,则说明出错;如果根节点不同,分别为px,
py,则将px和py合并,然后根据X和px的关系,X和Y的关系,y和py的关系,得到px和py的关系。

关于带权并查集

带权并查集和普通并查集最大的区别在于带权并查集合并的是可以推算关系的点的集合(可以通过集合中的一个已知值推算这个集合中其他元素的值)。而一般并查集合并的意图在于这个元素属于这个集合。带权并查集相当于把“属于”的定义拓展了一下,拓展为有关系的集合。

实现(c++)

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#define MAX_ANIMAL_NUM 50010
int gPar[MAX_ANIMAL_NUM]; //集合的根节点
int gRel[MAX_ANIMAL_NUM]; //节点和所属集合的根节点之间的关系 //gRel[i] == 0, i 和它的最老祖先是同类动物
//gRel[i] == 1, i 吃它的最老祖先
//gRel[i] == 2, i 的最老祖先吃它
void Init(int n){
for (int i = 1; i <= n; i++){
gPar[i] = i;
gRel[i] = 0;
}
} //获得集合的根节点,同时维护信息,主要是更新 节点到跟节点的关系数组 gRel[x]
int GetPar(int c){
if (c != gPar[c]){
int p = gPar[c]; //c还没被进行路径压缩前,节点c所属集合的根节点 p
gPar[c] = GetPar(gPar[c]); //进行路径压缩,路径压缩之后,递归函数返回时,p已经设置了根节点,同时也设置了p和总集合的根节点的关系
gRel[c] = (gRel[c] + gRel[p]) % 3; //根据c和p的关系,以及p和总集合的根节点的关系,设置c和总集合的根节点的关系
}
return gPar[c];
} int main(){
int N, K;
scanf("%d %d", &N, &K);
int rel, x, y;
int error_count = 0;
Init(N);
for (int i = 0; i < K; i++){
scanf("%d %d %d", &rel, &x, &y);
if (x > N || y > N){
error_count++;
continue;
}
rel--;
int p1 = GetPar(x), p2 = GetPar(y);
if (p1 == p2){
if ((gRel[x] + 3 - gRel[y]) % 3 != rel){ //关系不一致
error_count++;
}
}
else{ //对集合进行合并,同时需要注意,根据 x-->p1, x->y, y->p2的关系,得到 p1->p2的关系
gPar[p1] = p2;
gRel[p1] = (3 - gRel[x] + rel + gRel[y]) % 3;
}
}
printf("%d\n", error_count);
return 0;
}

poj_1182 并查集的更多相关文章

  1. BZOJ 4199: [Noi2015]品酒大会 [后缀数组 带权并查集]

    4199: [Noi2015]品酒大会 UOJ:http://uoj.ac/problem/131 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 ...

  2. 关押罪犯 and 食物链(并查集)

    题目描述 S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用"怨气值"( ...

  3. 图的生成树(森林)(克鲁斯卡尔Kruskal算法和普里姆Prim算法)、以及并查集的使用

    图的连通性问题:无向图的连通分量和生成树,所有顶点均由边连接在一起,但不存在回路的图. 设图 G=(V, E) 是个连通图,当从图任一顶点出发遍历图G 时,将边集 E(G) 分成两个集合 T(G) 和 ...

  4. bzoj1854--并查集

    这题有一种神奇的并查集做法. 将每种属性作为一个点,每种装备作为一条边,则可以得到如下结论: 1.如果一个有n个点的连通块有n-1条边,则我们可以满足这个连通块的n-1个点. 2.如果一个有n个点的连 ...

  5. [bzoj3673][可持久化并查集 by zky] (rope(可持久化数组)+并查集=可持久化并查集)

    Description n个集合 m个操作 操作: 1 a b 合并a,b所在集合 2 k 回到第k次操作之后的状态(查询算作操作) 3 a b 询问a,b是否属于同一集合,是则输出1否则输出0 0& ...

  6. [bzoj3123][sdoi2013森林] (树上主席树+lca+并查集启发式合并+暴力重构森林)

    Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数 ...

  7. 【BZOJ-3673&3674】可持久化并查集 可持久化线段树 + 并查集

    3673: 可持久化并查集 by zky Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 1878  Solved: 846[Submit][Status ...

  8. Codeforces 731C Socks 并查集

    题目:http://codeforces.com/contest/731/problem/C 思路:并查集处理出哪几堆袜子是同一颜色的,对于每堆袜子求出出现最多颜色的次数,用这堆袜子的数目减去该值即为 ...

  9. “玲珑杯”ACM比赛 Round #7 B -- Capture(并查集+优先队列)

    题意:初始时有个首都1,有n个操作 +V表示有一个新的城市连接到了V号城市 -V表示V号城市断开了连接,同时V的子城市也会断开连接 每次输出在每次操作后到首都1距离最远的城市编号,多个距离相同输出编号 ...

随机推荐

  1. smtpclient 邮件发送测试

    SmtpClient smtp = new SmtpClient(); //实例化一个SmtpClient smtp.DeliveryMethod = SmtpDeliveryMethod.Netwo ...

  2. 【Unity笔记】角色信息常用访问器get/set

    玩家角色Player的实体类演示. // 访问器函数:角色姓名 public string PlayerName { get { return playerName; } set { playerNa ...

  3. Hadoop的集群和优化

    Hadoop的集群和优化 Hadoop集群规模小到几个节点就可以组件一个集群,大到由几千个节点组成的超大集群. 在安装Hadoop集群时,把要安装的软件解压到集群内的所有机器上,软件的安装目录也要一致 ...

  4. 【SpringMVC笔记】第一课-框架执行过程

    SpringMVC模型的执行流程

  5. Java NIO使用及原理分析(二)(转)

    在第一篇中,我们介绍了NIO中的两个核心对象:缓冲区和通道,在谈到缓冲区时,我们说缓冲区对象本质上是一个数组,但它其实是一个特殊的数组,缓冲区对象内置了一些机制,能够跟踪和记录缓冲区的状态变化情况,如 ...

  6. Java命令学习系列(三)——Jmap

    Java命令学习系列(三)——Jmap 2015-05-16 分类:Java 阅读(479) 评论(0) Jmap jmap是JDK自带的工具软件,主要用于打印指定Java进程(或核心文件.远程调试服 ...

  7. 老生常谈:vim 配置

    1.自动补全 插件名字:NeoComplCache 下载地址:http://www.vim.org/scripts/script.php?script_id=2620 配置:把文件直接复制到vimfi ...

  8. 04 memory structure

    本章提要--------------------------------------------------SGA: System Global Area ( 包括background process ...

  9. HBase的rowkey设计(含实例)

    转自:http://www.aboutyun.com/thread-7119-1-1.html 对于任何系统的数据设计,我们都想提高性能,达到资源最大化利用,那么对于hbase我们产生如下问题: 1. ...

  10. 关于Cocos2d-x物理引擎用到的类和使用

    其实就是这三类PhysicsWorld类,PhysicsBody类,PhysicsShape类. 1.PhysicsWorld类 PhysicsWorld对象代表Cocos2d-x中的物理世界,这个世 ...