POJ 1182 食物链 带权并查集
来源:互联网 发布:查看windows序列号 编辑:程序博客网 时间:2024/06/12 00:23
食物链
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 77869 Accepted: 23180
Description
动物王国中有三类动物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),输出假话的总数。
Input
第一行是两个整数N和K,以一个空格分隔。
以下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
Noi 01
分析:
大概是第一次做带权并查集的题,感觉这道题好巧,各种公式什么的理解了好久。
并查集可以查询两个元素是否在同一个元素里,并且很快地合并两个集合。而这道题在并查集简单地合并与查询元素关系的基础上,还加入了元素的权值。(因为这次的关系除了是否同属于一种元素外,还有吃与被吃的关系。)
我们用rk来存储每个元素的关系。其中定义rk的含义如下:
rk==0,表示父子属于同一种元素
rk==1,这个节点被父节点吃
rk==2,父节点被这个节电吃
这样定义之后会有很多方便之处。
直接解释几个公式吧:
rk[g]=(rk[s]+rk[f])%3
这个在路径压缩的时候会用到,即已知一个节点与父节点的关系和父节点和爷爷节点的关系,求这个节点与爷爷节点的关系。
【这个可以自己手动推一下,对每种情况都是满足的
rk[x]+3-rk[y]
这个是在判断x和y是否是同一类的时候用到的。
如果x对y的关系是rk[x],那么y对x的关系就是(3-rk[x])%3 【这个也可以简单模拟一下,不难得出
那么x接rt,关系为rk[x],y也接rt ,关系为rk[y] 我们就可以先得出rt与y的关系,此时x与y就是爷孙关系(感觉这句话好奇怪),然后就可以求出x与y的关系,再与给出的关系判断一下是否一致就可。
注意:如果给出的x和y的关系是0,那么我们只需要判断rk[x]和rk[y]是否一致就可。(不过用这个式子也可以)
rk[fx]=(tmp-1+3-rk[x]+rk[y])%3
tmp为给出的关系。
此时为给出的x和y之前没有在一个集合中(肯定不是谎话),我们需要把x的根fx接在y的根fy上。
具体实现相当于把fx接在x上,x接在y上,y在fy上。
(但要路径压缩)
首先先利用tmp-1得到y与x的关系
再利用3-rk[x] 得到fx对于x的关系
此时就得到了fx与y的关系:
rk[fx]=(tmp-1+3-rk[x])%3;
最后再利用第一个式子得到fx与fy的关系,即给出的式子
马丹理解这些公式理解了好久,但理解完感觉成就感up2333
【好久没写过这么长的博客了
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();} return x*f;}const int N = 100010;int ans=0;int n,k;int fa[N],rk[N];int find(int x){ if(x==fa[x]) return x; int y=find(fa[x]); rk[x]=(rk[x]+rk[fa[x]])%3; return fa[x]=y;}int query(int tmp,int x,int y){ int fx=find(x),fy=find(y); if(fx==fy){ if(tmp==1){ if(rk[x]!=rk[y]) return 1; return 0; } else{ if((rk[x]+3-rk[y])%3!=1) return 1; return 0; } } fa[fx]=fy; rk[fx]=(tmp-1+3-rk[x]+rk[y])%3; return 0;}int main(){ n=read(),k=read(); for(register int i=1;i<=n;i++) fa[i]=i,rk[i]=0; for(register int i=1;i<=k;i++){ int tmp=read(),x=read(),y=read(); if(x>n||y>n) {++ans;continue;} if(x==y&&tmp!=1) {++ans;continue;} ans+=query(tmp,x,y); } printf("%d\n",ans); return 0;}
- POJ 1182 食物链(带权并查集)
- poj 1182 食物链(带权并查集)
- poj 1182 食物链(带权并查集)
- POJ-1182 食物链 (带权并查集)
- POJ 1182 食物链(带权并查集)
- poj 1182 食物链 //带权并查集
- POJ 1182 食物链 (带权并查集)
- poj 1182 食物链 带权并查集
- poj 1182 食物链 【带权并查集】
- poj 1182 食物链(带权并查集)
- poj 1182 食物链(带权并查集)
- POJ 1182 食物链(带权并查集)
- POJ 1182 食物链 带权并查集
- POJ 1182 食物链 带权并查集
- poj 1182食物链(带权并查集)
- poj 1182 食物链 带权并查集
- POJ 1182 食物链(带权并查集)
- Poj 1182 食物链【带权并查集】
- maven eclipse搭建web项目并发布到tomcat
- 动态网页
- 模拟退火算法
- 扩展ASCII码字符对应UNICODE编码
- POI报表入门
- POJ 1182 食物链 带权并查集
- 图片转化为base64及上传
- Tomcat如何处理一个请求
- Eclipse+Maven创建webapp项目<一>
- 安装完 3ds Max ,开启时报 Error Loading Plus-in DLL
- 无锡乐琪科技有限公司的第一次面试经历
- 为什么,问题在哪?
- 文章标题
- 第三章 函数的增长