P2024 [NOI2001] 食物链 题解
前言
因为洛谷的题目本身就有很优秀的题解,所以本系列的主要是用于自身的学习打卡记录,如果在此基础上也能帮助到其他同学,那就再好不过了。顺带一提,可能有一定的内容是洛谷题解基础上增加了自己的理解构成的,侵,联,删。
一、题面
1. 原题(贴图)
二、解析及AC代码
1.解析
本题很明显考查的是并查集,但是有三种不同的生物,各自还有同类,食物和天敌,好复杂啊!!!怎么办呢?
如果我们只使用一个并查集的话,明显存不下这么多的信息,那么我们就用三个来存就好了嘛(多就是美,大就是好)
注意,我们更新时需要要将三种不同的信息都更新哦
那么,此时同学们就可以自己去尝试一下了,如果还是不太理解,可以参考下博主下面的AC代码,会带有一定的注释哦
2.AC代码
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
const int N = 1e5 + 10;
int res;
//p[N]部分存本身,p[2*N]部分存猎物,p[3*N]部分存天敌
int p[N * 3];
int find(int x)
{
if (p[x] != x)p[x] = find(p[x]);//压缩路径
return p[x];
}
int main()
{
int n,k;
scanf("%d %d", &n, &k);
for (int i = 1; i <= n * 3; i++)p[i] = i;
while(k--)
{
char in[2];
int a, b;
scanf("%s %d %d", &in, &a, &b);
if (a > n || b > n)
{
res++;
continue;
}
if (*in == '1')
{
//注意到底是要使用树根(即p[find(x)]),还是探测树根find(x)
if (find(a + n) == find(b) || find(b + n) == find(a))res++;
else p[find(a)] = find(b), p[find(a + n)] = find(b + n), p[find(a + 2 * n)] = find(b + 2 * n);
}
else if (*in == '2')
{
//注意到底是要使用树根(即p[find(x)]),还是探测树根find(x)
if (find(b + n) == find(a) || find(a) == find(b)) res++;
else p[find(a + n)] = find(b), p[find(a)] = find(b + 2 * n), p[find(a + 2 * n)] = find(b + n);
}
}
printf("%d", res);
return 0;
}
如果觉得有用还请点个赞吧,拜托拜托