AcWing 240. 食物链
题面:
有三类动物, 吃 , 吃 , 吃 。
现有个动物,以 编号,每个动物都是 中的一种。
用两种说法对这个动物所构成的食物链关系进行描述:
第一种说法是1 X Y
,表示和 是同类。
第二种说法是2 X Y
,表示吃 。
一共句话,当一句话满足下列三条之一时,这句话就是假话,否则就是真话:
1、当前的话与前面的某些真的话冲突,就是假话;
2、当前的话中或 Y 比 大,就是假话;
3、当前的话表示吃 ,就是假话。
输出假话总数。
原题链接:240. 食物链 - AcWing
并查集:维护额外信息
扩展域
建立一个初始域和两个扩展域,分别为同类域 p[x]
、捕食域 p[x+n]
和被捕食域 p[x+n+n]
。
#include<bits/stdc++.h> using namespace std; const int N = 5e5 + 10; int n, k, x, y; int cnt, op; int p[3 * N]; int find(int x) { if (p[x] != x) p[x] = find(p[x]); return p[x]; } int main() { cin >> n >> k; //建立扩展域时,注意三个域都需要赋初值 for (int i = 1; i <= 3 * n; i++) p[i] = i; while (k--) { cin >> op >> x >> y; // x或y比n大,或x吃x,即为假话 if (x > n || y > n || (x == y && op == 2)) { cnt++; continue; } if (op == 1) { //如果x捕食y,或者y捕食x,即为假话 if (find(x + n) == find(y) || find(y + n) == find(x)) cnt++; else { p[find(x)] = find(y); p[find(x + n)] = find(y + n); p[find(x + n + n)] = find(y + n + n); } } else { //x与y为同类,或者y捕食x(x在y的捕食域中),即为假话 if (find(x) == find(y) || find(x) == find(y + n)) cnt++; else { p[find(x + n)] = find(y); p[find(x + n + n)] = find(y + n); p[find(x)] = find(y + n + n); } } } cout << cnt; }
带边权
p[]
数组:储存当前点所在集合的根节点;d[]
数组:储存该点到其根节点的距离。
数组更新的原则:该节点到根节点的距离 = 该点到父节点的距离 + 父节点到根节点的距离find()
函数的作用:- 寻找根节点,确定节点所在集合;
- 更新当前节点到根节点的距离。
同余定理的应用:同一集合内必然同余
- 同余定理:给定一个正整数
,如果两个整数 和 满足 能够被 整除,即 得到一个整数,那么就称整数 和 对模 同余。 - 对于当前节点到根节点的距离
可得, :同类; 、 :捕食; 、 :被捕食。
因为三种关系为线性轮回,所以已知 捕食 , 捕食 ,就可以得出 能捕食 。
#include<bits/stdc++.h> using namespace std; const int N = 1e5 + 10; int n, k, x, y; int cnt, op; int p[N]; //根节点 int d[N]; //到根节点的距离 int find(int x) { if (p[x] != x) { int t = find(p[x]); d[x] += d[p[x]]; p[x] = t; } return p[x]; } int main() { cin >> n >> k; for (int i = 1; i <= n; i++) p[i] = i; while (k--) { cin >> op >> x >> y; // x或y比n大,或x吃x,即为假话 if (x > n || y > n || (x == y && op == 2)) { cnt++; continue; } int px = find(x); int py = find(y); int t = d[x] - d[y]; if (op == 1) { //同类却不同余,即为假话 if (px == py && t % 3) cnt++; else if (px != py) { p[px] = py; d[px] = d[y] - d[x]; } } else { if (px == py && (t - 1) % 3) cnt++; else if (px != py) { p[px] = py; d[px] = d[y] + 1 - d[x]; } } } cout << cnt; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!