题目链接

http://poj.org/problem?id=1182

思路

前面做的带权并查集的权值记录该结点与其父结点是否是同一类,只有两种取值情况(0,1),在这题中某结点a和其父结点b的取值共有三种情况:a和b同类;a被b吃;a吃b,对应三种情况,r[a]的取值分别为0,1,2。这题的难点是递推公式,路径压缩递推公式为r[x] = (r[x] + r[t]) % 3,合并集合递推公式为r[ra] = (3 - r[a] + d - 1 + r[b]) % 3,递推公式形式的推导可以参考这篇文章

代码

 #include <cstdio>

 const int N =  + ;
int p[N];
int r[N]; void make_set(int n)
{
for (int i = ;i <= n;i++)
{
p[i] = -;
r[i] = ;
}
} int find_root(int x)
{
if (p[x] == -)
return x; int t = p[x];
p[x] = find_root(p[x]);
r[x] = (r[x] + r[t]) % ; //路径压缩递推公式
return p[x];
} int union_set(int d, int a, int b)
{
int ra = find_root(a);
int rb = find_root(b); if (ra != rb) //a,b不在同一集合,合并
{
p[ra] = rb;
r[ra] = ( - r[a] + d - + r[b]) % ; //合并集合递推公式
return ;
}
else
{
if ((r[a] + - r[b]) % != d - )
return ;
else return ;
}
return ;
} int main()
{
//freopen("poj1182.txt", "r", stdin);
int n, k;
scanf("%d%d", &n, &k);
make_set(n);
int d, x, y;
int ans = ;
for (int i = ; i < k;i++)
{
scanf("%d%d%d", &d, &x, &y);
if (x > n || y > n || (d == && x == y))
ans++;
else ans+=union_set(d, x, y);
}
printf("%d\n", ans);
return ;
}

参考:

1、http://www.voidcn.com/article/p-mwvpmony-qx.html

2、https://www.cnblogs.com/zhuanzhuruyi/p/5863738.html

最新文章

  1. JavaIO流文件的操作总结
  2. [Android Pro] Android以root起一个process[shell脚本的方法]
  3. SmartWiki文档在线管理系统简介
  4. Word2010撤销按钮失效,Ctrl+Z失效解决办法
  5. C#关于Sort排序问题
  6. oracle----修改表中的数据
  7. mysql添加超级管理员
  8. 解决CSS中float:left后需要clear:both清空
  9. golang 详解defer
  10. 双机热备ROSE HA工作原理
  11. [Kafka] [All about it]
  12. Confluence 6 通过 SSL 或 HTTPS 运行 - 修改你 Confluence 的 server.xml 文件
  13. python基础学习5----字典
  14. malloc 函数详解
  15. Oracle SQL部分练习题
  16. Ubuntu下navicat过期解决办法
  17. UESTC--1730
  18. 【转】java中定义二维数组的几种写法
  19. oracle 国外网站【转载】
  20. MAPREDUCE的原理和使用

热门文章

  1. 快速搭建Spring Boot项目
  2. 《java语言程序设计》初步学习——各种小Demo
  3. soj1022. Poor contestant Prob
  4. 什么是EOF -- 转
  5. PHPCMS v9 安全防范教程!
  6. 【译】第六篇 Replication:合并复制-发布
  7. python作业ATM(第五周)
  8. flask基础之app初始化(四)
  9. gcc编译选项【转】
  10. MySQL主从复制-指定数据库复制