AcWing 240. 食物链
原题链接:AcWing 240. 食物链
扩展域与边带权的并查集:
并查集实际上是由若干颗树构成的森林,我们可而一再数中的每条边上记录一个权值,即维护一个,用保存节点到父节点之间的边权。每次路径压缩之后,每个访问过的节点都会直接指向树根,然后同时更新这些节点的值,就可以利用路径压缩过程来统计每个节点到树根之间的路径上的信息。
代码:
int find(int x) {
if (p[x] != x) {
int t = find(p[x]);
d[x] += d[p[x]];
p[x] = t;
}
return p[x];
}
就题论题,这道题不像是一个食物链倒是像一个食物环,吃,吃,吃。
使用扩展域并查集,把有关系的动物放到一个集合里,使每个节点与其集合的根节点产生关系,设当前节点为,那么其距离;如果可以吃根节点,那么;如果可以被根节点吃,那么。那么这样每两个节点的关系都可以由它们与根节点的关系得来,如果是同类,那说明。
如果是同类,那么:
- 如果两者根节点相等但是距离不符合那么说明矛盾。
- 如果两者根节点不同那就插入到同一个集合中。
看下图,是同类肯定满足, 所以
如果不是同类,那么:
- 如果两者根节点相等但是距离不符合吃:那么说明矛盾。
- 如果两者根节点不同那就插入到同一个集合中。
看下图,不是同类那么就得是吃,那么说明在情况下,,所以
// Problem: 食物链
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/description/242/
// Memory Limit: 64 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
using namespace std;
const int N = 50010;
int p[N], 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() {
int n, m;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) p[i] = i, d[i] = 0;
int res = 0;
while (m--) {
int t, x, y;
scanf("%d%d%d", &t, &x, &y);
if (x > n || y > n) res++;
else {
int px = find(x), py = find(y);
if (t == 1) {
//如果是同类在一个集合中但距离不符合
if (px == py && (d[x] - d[y]) % 3 != 0) res++;
else if (px != py) {
p[px] = py;
d[px] = d[y] - d[x];
}
} else {
//如果是非同类在一个集合中判断是否满足x吃y
if (px == py && (d[x] - d[y] - 1) % 3 != 0) res++; //非同类
else if (px != py) {
p[px] = py;
d[px] = d[y] + 1 - d[x];
}
}
}
}
printf("%d\n", res);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端