【带权并查集】POJ1182 [NOI2001]食物链
来源:互联网 发布:软件的版权声明 编辑:程序博客网 时间:2024/04/28 10:33
题面在这里
这是一道经典的带权并查集例题。
我们定义权值s[i]表示节点i与根的关系:
0:和根是同一种动物
1:i能够吃根节点
2:i被根节点吃
这样定义的好处就是,在模3的意义下,各个节点之间的关系能够传递
(接下来本题解所讨论的范围都是在模3的意义下)
例如:
这样我们的权值s[i]就能满足一维向量加法了。
那么很显然,s[i]也满足一维向量减法:
a与b的关系就是s[a]-s[b]
再来考虑如何解此题:
若给出的X,Y未确定关系(X,Y拥有不同的根)显然这句话是对的,
然后把X,Y所在集合合并。
这里讲一下合并时权值如何修改:
设当前语句的条件是t(即x与y的关系),x、y的根分别是fx,fy
有:s[x]+?=t+s[y]
即:?=t+s[y]-s[x]
那么合并就是这样的:
fa[fx]=fy s[fx]=t+s[y]-s[x]
剩下的情况就是不用修改的,注意这时X,Y已经有公共祖先了
可以得到X,Y的关系是s[x]-s[y]
只需判断s[x]-s[y]是否与给定关系t相等即可
代码:
#include<cstdio>#include<cstring>const int maxn=50005;int n,q,fa[maxn],s[maxn],ans=0;inline int red(){ int tot=0;char ch=getchar(); while (ch<'0'||'9'<ch) ch=getchar(); while ('0'<=ch&&ch<='9') tot=tot*10+ch-48,ch=getchar(); return tot;}int getfa(int x){ if (fa[x]==x) return x; int father=fa[x]; fa[x]=getfa(fa[x]); s[x]=(s[x]+s[father])%3; return fa[x];}int main(){ n=red(),q=red(); for (int i=1;i<=n;i++) fa[i]=i; while (q--){ int ch=red(),x=red(),y=red(); if (x>n||y>n) {ans++;continue;} if (ch==1){ int fx=getfa(x),fy=getfa(y); if (fx!=fy) fa[fx]=fy,s[fx]=(s[y]-s[x]+3)%3;else ans+=(s[x]-s[y]+3)%3!=0; }else{ int fx=getfa(x),fy=getfa(y); if (fx!=fy) fa[fx]=fy,s[fx]=(s[y]-s[x]+4)%3;else ans+=(s[x]-s[y]+3)%3!=1; } } printf("%d",ans); return 0;}
3 0
- 【带权并查集】POJ1182 [NOI2001]食物链
- 并查集/poj1182 noi2001食物链eat
- POJ1182 【NOI2001】 食物链 <种类并查集>
- poj1182食物链(带权并查集)
- poj1182(食物链)----带权并查集
- POJ1182-食物链(带权并查集)
- poj1182 食物链【带权并查集】
- POJ1182 食物链 带权并查集
- POJ1182 食物链 (带权并查集)
- poj1182 食物链 (带权并查集)
- 带权并查集模板(poj1182食物链验证)
- poj1182食物链(带权并查集+路径压缩)
- 食物链 POJ1182(带权并查集)
- POJ1182 食物链(带权并查集,非常经典)
- poj1182 食物链 带权并查集 偏移量
- poj1182食物链(带权并查集)
- NOI2001 食物链 并查集
- 【NOI2001】 食物链 并查集
- ssh框架整合时的一点异常总结
- 安卓逆向系列教程 4.9 破解内购 II
- 关于java中的File.seperator
- 一文看懂机械键盘,从小白到行(ru)家(shou)
- VMware MAC地址修改
- 【带权并查集】POJ1182 [NOI2001]食物链
- NIO基本读写
- 371. Sum of Two Integers
- eoprocessing with Python using Open Source GIS
- 程序员是个大江湖之我来自编译门
- C#笔记1
- CF
- sizeof 和 strlen 在求解数组 字符数组 字符串 二维数组时候的小结
- 继承