传送门

经典的并查集问题

对于这种问题,并查集需要分类

开3*n的并查集,其中x用来连接与x同类的,x+n用来连接x吃的,x+2*n用来连接x被吃的。

1 x y时,如果 x吃y 或 x被y吃,那么为假话,

否则x与y同类,x吃的y也吃,x被吃的y也被吃;

2 x y时,如果 x与y同类(x与x自然也是同类) 或 y吃x,那么为假话,

否则x吃y,y被x吃,y吃x被吃的.

——代码

 #include <cstdio>
#include <iostream>
#define N 1000001 int n, k, ans;
int f[N]; inline int read()
{
int x = , f = ;
char ch = getchar();
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -;
for(; isdigit(ch); ch = getchar()) x = (x << ) + (x << ) + ch - '';
return x * f;
} inline int find(int x)
{
return x == f[x] ? x : f[x] = find(f[x]);
} inline void connect(int x, int y)
{
x = find(x);
y = find(y);
if(x ^ y) f[x] = y;
} int main()
{
int i, j, x, y, z;
n = read();
k = read();
for(i = ; i <= * n; i++) f[i] = i;
for(i = ; i <= k; i++)
{
z = read();
x = read();
y = read();
if(x > n || y > n)
{
ans++;
continue;
}
if(z == )
{
if(find(x + n) == find(y) || find(x + * n) == find(y))
{
ans++;
continue;
}
connect(x, y);
connect(x + n, y + n);
connect(x + * n, y + * n);
}
else
{
if(find(x) == find(y) || find(x + * n) == find(y))
{
ans++;
continue;
}
connect(x + n, y);
connect(y + * n, x);
connect(y + n, x + * n);
}
}
printf("%d\n", ans);
return ;
}

还有带权并查集的做法

这道题的特殊之处在于对于任意一个并查集,只要告诉你某个节点的物种,你就可以知道所有节点对应的物种。

比如一条长为4的链 甲->乙->丙->丁 ,我们知道乙是A物种。那么甲一定是B物种,因为A只吃B物种,不吃C物种或是自己的同类。同样的丙一定是C物种,丁是B物种。

也就是说,每一条链上都是A、B、C物种循环,这也是我们寻找不合逻辑的假话的出发点。

我们可以定义数组d[i]表示节点i到根节点距离mod3的结果帮助解题。

我们统计谎话的数量,那么我们把谎话这样分类:

第一类叫弱智的谎话,包括

(1)自己吃自己的同类是谎话,表述为d==2&&x==y(其中x y是我们读入的量);

(2)编号超出限制,表述为x>n||y>n。 第二类叫不弱智的谎话,包括d==1和d==2这样两类。

(1)d==1。

我们先要考虑x y是否在同一个并查集中,这是判断真假话的前提。

如果x y 不在同一个并查集中,那么关于他们的任何表述都可以是真的。

比如两条链:1->2->3->4->5 6->7->8->9

如果我说1和6是同类,那么自然地,2与7,3与8,4与9成为同类。

我们任意的选取两个数是同类都是符合的。

下面我们要做的就是把两个并查集合并。

d[f[x]]=(d[y]-d[x]+3)%3;//关于距离

f[f[x]]=f[y];//关于父亲

如果x y在同一个并查集中,那么违反距离关系的话一定是假话。

d[x]!=d[y]//关于距离

(2)d==2。

还是先看x y是否在一个并查集中,如果不在,那么合并并查集;如果在,那么根据距离关系找出假话。

——代码

 #include <cstdio>
#include <iostream>
#define N 1000001 int n, k, ans;
int f[N], d[N]; inline int read()
{
int x = , f = ;
char ch = getchar();
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -;
for(; isdigit(ch); ch = getchar()) x = (x << ) + (x << ) + ch - '';
return x * f;
} inline int find(int x)
{
if(x ^ f[x])
{
int fx = f[x];
f[x] = find(f[x]);
d[x] = (d[x] + d[fx]) % ;
}
return f[x];
} int main()
{
int i, j, x, y, z;
n = read();
k = read();
for(i = ; i <= n; i++) f[i] = i;
for(i = ; i <= k; i++)
{
z = read();
x = read();
y = read();
if(x > n || y > n)
{
ans++;
continue;
}
if(z == )
{
if(find(x) == find(y))
{
if(d[x] ^ d[y]) ans++;
}
else
{
d[f[x]] = (d[y] - d[x] + ) % ;
f[f[x]] = f[y];
}
}
else
{
if(find(x) == find(y))
{
if(d[x] ^ ((d[y] + ) % )) ans++;
}
else
{
d[f[x]] = (d[y] - d[x] + ) % ;
f[f[x]] = f[y];
}
}
}
printf("%d\n", ans);
return ;
}

最后是关于合并两个根时两根之间的距离的解释:

设合并后两根距离为a(即要求的量)

R[i]表示点i到他们原来祖先的距离,途中所有线段长都可以表示。

注意每条边的长度是不一样的,∴R[x]+a-R[y]≠R[x],而等于x、y的距离即食物关系(大家可以往下翻,下面有关于这个的讲解)

设该距离为t

方程:R[x]+a-R[y]=t,整理得a=t-R[x]+R[y],当然把x与y换一下也是成立的,这取决于你的程序。

[luoguP2024] 食物链(并查集)的更多相关文章

  1. 编程算法 - 食物链 并查集 代码(C)

    食物链 并查集 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 有N仅仅动物, 分别编号为1,2,...,N. 全部动物都属于A,B,C中的一种 ...

  2. [poj1182]食物链(并查集+补集)

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

  3. POJ 1182 (经典食物链 /并查集扩展)

    (參考他人资料) 向量偏移--由"食物链"引发的总结 http://poj.org/problem?id=1182这道食物链题目是并查集的变型.非常久曾经做的一次是水过的,这次 ...

  4. P2024 [NOI2001]食物链 并查集

    题目描述 动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形.A 吃 B,B 吃 C,C 吃 A. 现有 N 个动物,以 1 - N 编号.每个动物都是 A,B,C 中的一种,但是我 ...

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

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

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

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

  7. poj1182食物链--并查集

    动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种.有人用两种说 ...

  8. POJ1182:食物链(并查集)

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

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

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

  10. POJ-1182 食物链 并查集(互相关联的并查集写法)

    题目链接:https://cn.vjudge.net/problem/POJ-1182 题意 中文题目,就不写了哈哈 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃 ...

随机推荐

  1. php使用163邮箱发送邮件

    email.class.php文件 <? class smtp { /* Public Variables */ var $smtp_port; var $time_out; var $host ...

  2. $P5018 对称二叉树$

    problem 一直忘记给这个题写题解了. 这题挺水的吧. 挺后悔当时没写出来. #ifdef Dubug #endif #include <bits/stdc++.h> using na ...

  3. ACM_Jack拆炸弹(深搜)

    Jack拆炸弹 Time Limit: 2000/1000ms (Java/Others) Problem Description: 在一个由n*n个格子组成的监狱里被恐怖份子安置了一个定时炸弹.其中 ...

  4. Spark RDD/Core 编程 API入门系列之简单移动互联网数据(五)

    通过对移动互联网数据的分析,了解移动终端在互联网上的行为以及各个应用在互联网上的发展情况等信息. 具体包括对不同的应用使用情况的统计.移动互联网上的日常活跃用户(DAU)和月活跃用户(MAU)的统计, ...

  5. Unity相机平滑跟随

    简介 unity中经常会用到固定视角的相机跟随,然后百度发现大家都是自己写的,然后偶也写咯一个,分享一下 PS: 由于刚学C#不久,才发现delegate这个东东,也不知道对性能影响大不大,但是看MS ...

  6. Unity学习-摄像机的使用(六)

    快速对齐摄像机 [选择摄像机-GameObject-Align With View] Game模板中显示的界面,就是摄像机拍摄后的画面 本次学习案例 添加一个地形,一个点光源,三个Cube   了解摄 ...

  7. 从"嘿,今晚..."谈消息安全传输中的技术点

    一.初级阶段:信息裸传 特点:在网络上传递明文 黑客定理一:网络上传递的数据是不安全的,属网络于黑客公共场所,能被截取 结果:传递明文无异于不穿衣服裸奔 改进方案:先加密,再在网络上传输 二.进阶阶段 ...

  8. Matrix computations in C

    meschach配置使用 *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !im ...

  9. hibernate Hql 更新的参数只能设置String类型

    最近在项目中发现一个奇怪的现象,请看下面的代码 实体类MyEmployeeEntity @Table(name="myemployee") public class MyEmplo ...

  10. log4j最全教程

    (转自http://www.codeceo.com/article/log4j-usage.html) 日志是应用软件中不可缺少的部分,Apache的开源项目log4j是一个功能强大的日志组件,提供方 ...