思路:设r(x)表示节点x与根结点的关系,px表示x的根结点。记录每个节点与其父节点的关系,就能很方便知道每个节点以及和它的父节点的关系。

  1. struct node{
  2. int par; //父亲节点
  3. int rel; //与父节点的关系
  4. }a[maxn];
  5. //关系:0表示同类, 1表示父节点吃子节点, 2表示子节点吃父节点

现在给定节点x和y,它们的关系是rel,如何判断这句话是真还是假?

利用find函数找到它们的根结点px和py,以及它们和各自根结点的关系r(x)和r(y),如果px!=py说明x和y没有位于同一集合,那么这句话不会和任何话发生冲突,即这一定是真话,然后合并两个集合;另一种情况就是px==py,说明x和y位于同一集合,现在已经得到x(x)和r(y),那么如何知道x和y的关系呢?我先介绍一下find函数的实现:

  1. int find(int x, int &r) {
  2. if(a[x].par == x) {
  3. r = x;
  4. return a[x].rel;
  5. }
  6. int y = find(a[x].par, r);
  7. a[x].par = r; //路径压缩
  8. return a[x].rel = (a[x].rel + y) % 3;
  9. }

find函数每次返回当前节点与根结点的关系,那么在已知当前节点和它的父亲节点关系,父亲节点和根结点的关系,很容易得到当前节点与跟节点的关系r(x) = ( r(a[x].par) + a[x].rel) % 3

同样对于上面的问题,只需要变换一下x、root、y三者的关系,也能求得x和y的关系r(x, y),如果r(x, y) == rel,说明是真话,否则假话。

注意:所有的关系转换都利用了find函数中的思想,请保证明确关系转换才能看懂unionset函数。

AC代码

  1. #include <cstdio>
  2. #include <cmath>
  3. #include <cctype>
  4. #include <algorithm>
  5. #include <cstring>
  6. #include <utility>
  7. #include <string>
  8. #include <iostream>
  9. #include <map>
  10. #include <set>
  11. #include <vector>
  12. #include <queue>
  13. #include <stack>
  14. using namespace std;
  15. #pragma comment(linker, "/STACK:1024000000,1024000000")
  16. #define eps 1e-10
  17. #define inf 0x3f3f3f3f
  18. #define PI pair<int, int>
  19. typedef long long LL;
  20. const int maxn = 50000 + 5;
  21. struct node{
  22. int par; //父亲节点
  23. int rel; //与父节点的关系
  24. }a[maxn];
  25. //关系:0表示同类, 1表示父节点吃子节点, 2表示子节点吃父节点
  26.  
  27. int find(int x, int &r) {
  28. if(a[x].par == x) {
  29. r = x;
  30. return a[x].rel;
  31. }
  32. int y = find(a[x].par, r);
  33. a[x].par = r; //路径压缩
  34. return a[x].rel = (a[x].rel + y) % 3;
  35. }
  36.  
  37. bool unionset(int x, int y, int rel) {
  38. int px, py;
  39. int rx = find(x, px), ry = find(y, py);
  40. if(px != py) { //位于同一集合
  41. ry = (3 - ry) % 3;
  42. a[py].par = px; //合并
  43. a[py].rel = (ry + rel + rx) % 3;
  44. return true;
  45. }
  46. else {
  47. rx = (3 - rx) % 3;
  48. if(rel == (rx + ry) % 3) return true;
  49. return false;
  50. }
  51. }
  52.  
  53. int main() {
  54. int n, k;
  55. while(scanf("%d%d", &n, &k) == 2) {
  56. for(int i = 1; i <= n; ++i) { //初始化并查集
  57. a[i].par = i;
  58. a[i].rel = 0;
  59. }
  60. int d, x, y, ans = 0;
  61. for(int i = 0; i < k; ++i) {
  62. scanf("%d%d%d", &d, &x, &y);
  63. if(x > n || y > n || (d == 2 && x == y)) {
  64. ans++;
  65. continue;
  66. }
  67. if(!unionset(x, y, d-1)) ans++;
  68. }
  69. printf("%d\n", ans);
  70. break; //只有一组数据
  71. }
  72. return 0;
  73. }

如有不当之处欢迎指出!

POJ - 1182 食物链 并查集经典的更多相关文章

  1. POJ 1182 食物链 [并查集 带权并查集 开拓思路]

    传送门 P - 食物链 Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u Submit  ...

  2. poj 1182 食物链 并查集 题解《挑战程序设计竞赛》

    地址 http://poj.org/problem?id=1182 题解 可以考虑使用并查集解决 但是并不是简单的记录是否同一组的这般使用 每个动物都有三个并查集 自己 天敌 捕食 并查集 那么在获得 ...

  3. POJ 1182 食物链(并查集的使用)

    食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 81915   Accepted: 24462 Description ...

  4. poj 1182 食物链 并查集的又一个用法

    食物链   Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 41584   Accepted: 12090 Descripti ...

  5. POJ 1182食物链(并查集)

    食物链Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 85474 Accepted: 25549Description动物王国中有三 ...

  6. poj——1182食物链 并查集(提升版)

    因为是中文题,题意就不说了,直接说思路: 我们不知道给的说法中的动物属于A B C哪一类,所以我们可以用不同区间的数字表示这几类动物,这并不影响结果,我们可以用并查集把属于一类的动物放在一块,举个例子 ...

  7. POJ 1182 食物链 (并查集)

    食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 50601   Accepted: 14786 Description ...

  8. POJ 1182 食物链(并查集)

    题目链接 经过宝哥的讲解,终于对这种问题有了进一步的理解.根据flag[x]和flag[y]求flag[tx]是最关键的了. 0吃1,1吃2,2吃0. 假设flag[tx] = X; 那么X + fl ...

  9. poj 1182 (关系并查集) 食物链

    题目传送门:http://poj.org/problem?id=1182 这是一道关系型并查集的题,对于每个动物来说,只有三种情况:同类,吃与被吃: 所以可以用0,1,2三个数字代表三种情况,在使用并 ...

随机推荐

  1. centos7安装python3.6

    安装python3.6可能使用的依赖 # yum install openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sql ...

  2. js禁止滚动条移动

    js禁止滚动条移动 var scrollFunc=function(e){ e=e||window.event; if (e&&e.preventDefault){ e.prevent ...

  3. ATS 分级缓存

    理解缓存分级cache hierarchies 缓存分级是由彼此能够相互通信的各级缓存组成的,ATS支持几种类型的缓存分级.所有的缓存分级都有父子缓存概念. 父缓存位于缓存分级的较高级别,ATS能将请 ...

  4. int main()还是void main()

    按照新的C99标准,即使函数本身没有定义返回值,编译器也会加上,以返回给激发程序,运行状态.很多人甚至市面上的一些书籍,都使用了void main( ) ,其实这是错误的.C/C++ 中从来没有定义过 ...

  5. [PHP]PDO占位符预处理在 IN 和 LIKE 中用法

    两点注意项: 1. 占位符 (?) 必须被用在整个值的位置,不需要引号等其它字符. 2. 参数按数组元素顺序依次传递给占位符. <?php /** * PDO基于占位符的查询预处理 * * @l ...

  6. CRM项目-1模型与站点管理

    一.项目环境 语言:python3 IDE:pycharm 组件:bootstarp,jQuery 二.模型 2.1编写模型 联合唯一 class Meta:显示中文名. 认证使用django自带的U ...

  7. 禁掉或启用firefox 的 javascript 脚本

    老版本的firefox可以直接在“选项”页设置启用或禁用javascript 脚本 新版的Firefox中,我找了半天,没有找到,看来是没法直接设置了 于是在 地址栏键入 about:config 搜 ...

  8. 用js脚本一键下载网页所有图片

    年前这两天稍微闲一点了,琢磨了一点js脚本,功能是把当前网页页面上的所有图片一次性保存到本地,免得每次都要对图片右键保存. 测试环境:Chrome开发者模式下(启动Chrome,按F12即可) 测试网 ...

  9. MUI体验框架

    1.      mui简介 1.1  缘起 1.基于jq的jqmobile,性能低的无法忍受,且UI难看 2.bootstrap这种响应式设计,性能在低端机不足,而且UI风格一看就是网页,不是App的 ...

  10. zend framework框架学习走起——从零开始,点击记录-安装

    zend framework第一步,先来安装下zend framework框架. 先介绍下,我这边的php配置环境,为图省事,我是安装wampserver来搭载php环境的,,php+Apache+m ...