POJ1182--食物链(经典并查集)并查集看不出来系列2
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 65906 | Accepted: 19437 |
Description
现有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),输出假话的总数。
Input
以下K行每行是三个正整数 D,X,Y,两数之间用一个空格隔开,其中D表示说法的种类。
若D=1,则表示X和Y是同类。
若D=2,则表示X吃Y。
Output
Sample Input
100 7
1 101 1
2 1 2
2 2 3
2 3 3
1 1 3
2 3 1
1 5 5
Sample Output
3
Source
这题算是对并查集应用的一个总结吧!
参考一另篇博客http://blog.csdn.net/c0de4fun/article/details/7318642,
大体思想:
1、如果两个物种有联系,不管是吃,被吃还是同类,它们之间应该是有一条径路可达的,
也就是它们在一个合集中。
2、如果a,b有关系,b,c有关系,那么a,c之间的关系式可以通过两者的关系推出来的。
OK,下面围绕着上面的两个思想来逐一拆分。
首先就是怎么把有关系的物种放到同一个合集中去,这就要需用到并查集了。每一次入输d,x,y,
也就是相当于x,y之间有一条权为d的径路。先忽略这个权值,直接斟酌路径,那并查集的路径建立就
不用我说了。一个parent数组,parent[i]表现从parent[i]到i有一条径路。OK,那不同的物食圈就构
成了一个连通区域。每个连通区域都有一个根点节。
下面斟酌怎么处理这个权
先说点数学的货色,任何一种偏序关系都足满自反、对称、传递。
自反:自己跟自己满足偏序关系。
对称:a,b的偏序关系为r,则b,a的偏序关系为~r.表现求反。
传递:a,b的偏序关系为r1,b,c的偏序关系为r2,a,c的偏序关系为r1+r2.
为了便利,用一个relation数组来维护这个权值。relation[i]表现的是i在所的连通区域的
根点节到i的关系。先略忽这个关系数组的维护过程,把团体的思绪理清晰。如果有两个物种加进来,
就有两种情况,要么它们在同一个连通集里头。要么不在同一个连通集里头。
一、两者在同一个连通集里头:
1、新加的关系表明x,y是同类,那么它们两个分别到连通区域根点节的关系应该是一样的,
要不就矛盾了。(记为case1)
2、如果新加的关系表明x,y不是同类,那么在当前参加y,x相对根节点的关系和x本来相对根点节的
关系应该是不变的,否则就矛盾了。(记为case2)
二、两者在不同的连通集里头:就直接连接两个连通集就能够了。(记为case3)
路径压缩处理:
由于后来物种会越来越多,我们不希望食物链拉的很长,所以会尽可能的让全部的点节都直接和根节点
相连。这样整个连通的图就有点呈现出星形。
怎么维护关系数组:
数组里头的每个元素的取值要么是0(同类),要么是1(父吃子),要么是2(子吃父)。至于为什么要
这么设置(因为题目中1表示同类,而我们定义0表示同类,相对都应该减一,所以题目中的2表示父吃子在我们这里
应该是2-1=1,,1表示父吃子),参考一另篇博客http://blog.csdn.net/c0de4fun/article/details/7318642,
这里是不能随便定义的。设前面的数据我已经处理好了,现在要处理d,x,y.为了叙说的便利,
记relation[x]为x根->x.那么在现就有三种情况:
case1:(同一个集合且同类)
这种情况x根与y根雷同。如果x根->x与y根->y不同,表明x,y不是同类,与d=1矛盾。
case2:(同一个集合但不同类)
这种情况x根与y根雷同。如果参加y之后,(x根->x) = (x根(即y根)->y + y->x),如果新求出来
的关系与本身已有的x根->x的关系不同,则矛盾。
case3:(在不同集合中)
这种情况x根与y根不同。由于这里添加的是x到y的一条有向边。将y根的父点节设置为x根,更新y根父点
节到x根的关系,即x根->y根=x根->x+x->y+y->y根,由于这里都是有向边,所以更新关系的时候注意关
系的方向。这里需要注意,我们只更新了两个根之间的关系,x根与原来的y所在的连通区域里头的节点
的关系都没有更新,这就是为什么要在一开始判断之前就要调用Find函数,更新每个点节到其根点节的
关系。
初始条件:
有了这个递推,就好办了。初始条件parent就是并查集一般的初始条件,父点节于等自己。由于初始的
时候父节点是自己,当然自己跟自己的关系肯定是同类咯,也就是relation[i]=0
代码:
#include <cstdio>
#include <iostream> using namespace std; const int N = ;
int father[N];
int relation[N];//根点节到点节的关系 void init(int n)
{
for(int i = ; i <= n; ++i)
{
father[i]= i;
relation[i] = ;
}
}
//更新的步调,先将当前点节与其根点节相连,然后更新其与根点节的关系
//当前节点x与根节点r的关系更新的方法:
// (x与其父点节的关系+其父点节的关系与根点节的关系)%3
//所以在更新节点x的数据之前需要更新其父节点的数据,这是find为什么搞成递归函数的原因
//其更新的次序是从根节点开始往下,始终到当前点节x的父点节。
int find(int x)
{
if(x != father[x])//不是根点节
{
int temp = father[x];
//将当前点节的父点节设置为根点节
father[x] = find(temp);
//更新当前点节与根点节的关系,由x->x父和x父->父根的关系失掉x->父根的关系
//所以在这之前必须更新其父点节与根点节的关系
relation[x] = (relation[x] + relation[temp]) % ;
}
return father[x];
} int main()
{
int n, m, x, y, d, fx, fy, cnt; while(~scanf("%d %d", &n, &m))//POJ上只要需一次入输,所以不要需while循环
{
cnt = ;
init(n);
for(int i = ; i < m; ++i)
{
scanf("%d %d %d", &d, &x, &y);
if(x > n || y > n)
{
++cnt;
continue;
}
if(d == && x == y)
{
++cnt;
continue;
}
fx = find(x);
fy = find(y);
if(fx == fy)//属于同一个子集
{
//如果x、y是同类,那么他们相对根点节的关系应该是一样的
if(d == && relation[x] != relation[y])
++cnt;
//如果不是同类,加入x与y的关系之后,x相对根点节的关系(x根->y,y->x(即3-(d-1)=2).即x根->x)应该是不变的
//这里d=2表示x - y = 2-1=1;而y->x=3-(x->y)=3-1=2;
if(d == && relation[x] != (relation[y] + )%)
++cnt;
}
else//合并两个连通区域
{
father[fy] = fx;//y根的父点节更新成x根
//(d-1)为x与y的关系,3-relation[y]是y与y的根点节的关系,注意方向,relation[x]是其根点节与x的关系
//x根->x,x->y,y->y根:即x根->y根
relation[fy] = (relation[x] + (d-) + (-relation[y])) % ;//注意这里只更新的是fy相对于根的关系
}
}
printf("%d\n", cnt);
}
return ;
}
POJ1182--食物链(经典并查集)并查集看不出来系列2的更多相关文章
- POJ1182 食物链---(经典种类并查集)
题目链接:http://poj.org/problem?id=1182 食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submission ...
- poj1182食物链,经典带权并查集
动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用两种 ...
- 并查集专辑 (poj1182食物链,hdu3038, poj1733, poj1984, zoj3261)
并查集专题训练地址,注册登录了才能看到题目 并查集是一个树形的数据结构, 可以用来处理集合的问题, 也可以用来维护动态连通性,或者元素之间关系的传递(关系必须具有传递性才能有并查集来维护,因为并查集 ...
- 【转】并查集&MST题集
转自:http://blog.csdn.net/shahdza/article/details/7779230 [HDU]1213 How Many Tables 基础并查集★1272 小希的迷宫 基 ...
- HDU 3038 How Many Answers Are Wrong (并查集)---并查集看不出来系列-1
Problem Description TT and FF are ... friends. Uh... very very good friends -________-bFF is a bad b ...
- legend3---21、查问题或者查插件的时候请搜索对关键词
legend3---21.查问题或者查插件的时候请搜索对关键词 一.总结 一句话总结: 比如要查移动端的js图片裁剪插件,直接搜就“移动端的js图片裁剪插件” 千万记得问题和找资料都搜索对关键词(搜索 ...
- PHP正则 正向预查&反向预查
了解正向预查&反向预查前,我们先要知道正则的2个函数:preg_match_all . preg_replace preg_match_all 可以看文章:点击查看 preg_replace ...
- docker 快速部署ES集群 spark集群
1) 拉下来 ES集群 spark集群 两套快速部署环境, 并只用docker跑起来,并保存到私库. 2)弄清楚怎么样打包 linux镜像(或者说制作). 3)试着改一下,让它们跑在集群里面. 4) ...
- Mongodb主从复制 及 副本集+分片集群梳理
转载努力哥原文,原文连接https://www.cnblogs.com/nulige/p/7613721.html 介绍了Mongodb的安装使用,在 MongoDB 中,有两种数据冗余方式,一种 是 ...
随机推荐
- HDU 3835 R(N)(枚举)
题目链接 Problem Description We know that some positive integer x can be expressed as x=A^2+B^2(A,B are ...
- Gentoo解决Udev升级的网卡重命名问题
问题描述: 配置网络时,很多新手运行ifconfig命令查看网卡时,会发现我们熟悉的eth0网卡没有了,或是发现一些不规则命名的东东,不错,那就是你的网卡. 因为内核升级(忘记具体哪个版本了)从ude ...
- 找斐波那契数列中的第N个数——递归与函数自调用算法
题目描述 Description 用递归的方法求斐波那契数列中的第N个数 输入输出格式 Input/output 输入格式:一行,一个正整数n输出格式: 一行,一个数,表示斐波那契数列中的第N个数 ...
- Weblogic的集群
<收藏自http://www.cnblogs.com/HondaHsu/p/4267972.html> 一.Weblogic的集群 还记得我们在第五天教程中讲到的关于Tomcat的集群吗? ...
- 配置pyqt5环境 for python3.4 on Linux Mint 17.1
1.安装QT 配置QT PATH 在 /etc/profile文件中追加 export QTDIR=/usr/local/Qt5.4.2/5.4/gcc_64 export LD_LIBRARY_PA ...
- C++模板之类型与数据绑定
有时候我们需要将类型与一些数据进行绑定,例如我们一般通过单例,将字符串与一个函数关联(一般称之为注册),之后通过字符串创建相关联的对象 class A { public: static A* Crea ...
- mongoDB5--mongoDB增删改查
之前我们探讨了mongodb的"增删改查",要知道,我们的增删改其实都离不开查询表达式,所以查询表达式在mongodb是非常重要的.关于查询其实我们只是介绍了以小部分.关于mong ...
- jQuery(1)——了解jQuery
jQuery 终于开始了jQuery的学习了,好开心,虽然感觉JavaScript并没有学好,尴尬.木事,咋们慢慢来.fighting [jQuery简介] jQuery是继Prototype之后又一 ...
- JavaScript(3)—— 正则表达式
---恢复内容开始--- 正则表达式 这是写的正则表达式,正则表达式的点比较多,也比较细.所以有些地方我们得注意的比较多.正则表达式在JS中是很重要的一个部分,其中他的语法都得牢记.不过最好还是理解性 ...
- 《LYFvs2013转vs2010》
<LYFvs2013转vs2010>1.修改解决方案文件(**.sln) 将-------------------------------------------------------- ...