POJ 1182 食物链
2015-11-03 15:37
260 查看
这是一道经典的并查集
类似线段树的区间更新,更新时不要更新到底层,查找时再更新
用有向距离表示关系,dis(a, b)为a到b的距离
令d = dis(a, b),注意:dis(a, b) = ( 3 - dis(b, a) ) % 3
d = 0 :a 与 b 同类
d = 1 :a 吃 b
d = 2 :b 吃 a
fa[i] : i 的父结点
dis[i] = dis(fa[i], i)
注意find函数的作用,find(n):更新dis
,fa
,返回n的根结点
更新完毕后,fa
是n所对应的根结点,故dis
为根结点到n的有向距离
高维也能类似解决
类似线段树的区间更新,更新时不要更新到底层,查找时再更新
用有向距离表示关系,dis(a, b)为a到b的距离
令d = dis(a, b),注意:dis(a, b) = ( 3 - dis(b, a) ) % 3
d = 0 :a 与 b 同类
d = 1 :a 吃 b
d = 2 :b 吃 a
fa[i] : i 的父结点
dis[i] = dis(fa[i], i)
注意find函数的作用,find(n):更新dis
,fa
,返回n的根结点
更新完毕后,fa
是n所对应的根结点,故dis
为根结点到n的有向距离
高维也能类似解决
#include <cstdio> int fa[50005], dis[50005]; int find(int n) { if(fa != n) { int t = find(fa ); dis = (dis + dis[fa ]) % 3; fa = t; } return fa ; } int main() { int n, k; scanf("%d%d", &n, &k); for(int i = 1; i <= n; i++) fa[i] = i, dis[i] = 0; int cnt = 0; for(int i = 0; i < k; i++) { int op, a, b; scanf("%d%d%d", &op, &a, &b); if(a > n || b > n) {cnt++; continue;} if(op == 2 && a == b) {cnt++; continue;} int x = find(a), y = find(b); int d = op - 1; if(x == y) { if(dis[b] % 3 != (dis[a] + d) % 3) cnt++; continue; } fa[y] = x; dis[y] = (dis[a] - dis[b] + d + 3) % 3; } printf("%d", cnt); return 0; }
相关文章推荐
- 创建 Win32 应用程序 (C++)
- 站台查询api 据站台名称查询站台详细信息
- CocoaPods
- 项目中遇到的问题:前台 disabled 与 后台disabled
- redis 存取键值对常用的三种使用方式 - Jedis、JedisPool、Jedis分布式
- Java的入门知识和准备步骤
- Nand flash ecc校验
- ubuntu14.04开启休眠(Hibernate)
- unity 2D 正交摄像机下 uGUi 比例与自适应问题
- Android Studio系列教程四--Gradle基础
- Javascript进阶篇——( 事件响应)笔记整理
- php empty,isset,is_null比较(差异与异同)
- linux下使用读写锁
- js获得日期操作,以及日期的格式化
- PHP中的浅复制与深复制
- 设计模式
- 内部跳转(请求转发)和外部跳转(重定向)的区别?
- 演进式例解控制反转(IoC)、依赖注入(DI)之一
- java list 根据对象的一个属性排序
- jsp页面的数显示两位小数