题目链接w:https://www.luogu.com.cn/problem/P2024
是一个考察并查集的题,代码实现比较简单但思路真的很难想?
看了半天qbxt课件才看懂思路hmmm(菜
大概意思就是建立一个有三层的并查集
如果两个动物是同类就把它们放在同一层
如果x吃y就把y放在x上面的一层 也就是y+n和x在同一个集合
具体来说:
(部分摘自课件)
对每个元素 x 建立 3个元素,xa,xb,xc。
其中xa = x,xb =x+n,xc =x+2*n
如果碰到“1 x y”,说明 x和y 是同类
如果 x 和 y + N 在一个集合里,ans++
如果 x 和 y + 2 * N 在一个集合里,ans++
合并 x 和 y, x + N 和 y + N,x + 2 * N 和 y + 2 * N
如果碰到“2 x y”,说明 x吃y
如果 x和y已经是同类,也就是x 和 y 在一个集合里,ans++
如果 y吃x也就是x 和 y + 2 * N 在一个集合里,ans++
合并x 和 y+N, x+N 和 y+2 * N,x+2 * N 和 y
补充
感觉上面解释的还是不太好懂,个人感觉根据样例手动把这个过程模拟一下会比较好理解hmmm
luogu里第一篇题解写的超级详细可以去看hmm
如果还是不懂就看代码叭
#include<iostream>
#include<cstdio>
using namespace std;
int read(){
int a = 0,f = 0;char p = getchar();
while(!isdigit(p)){f|=p=='-';p = getchar();}
while(isdigit(p)){a=(a<<3)+(a<<1)+(p^48);p = getchar();}
return f?-a:a;
}
int n,k;
int fa[300005];//记录祖先的并查集
int find(int x){
if(fa[x] == x)return x;
else return fa[x] = find(fa[x]);
}
int main(){
n = read();k = read();
int number,X,Y,ans = 0;
for(int i = 1; i <= 3*n;i ++)fa[i] = i;
for(int i = 1;i <= k;i ++){
number = read();
X = read();Y = read();
if(X > n||Y > n){
ans++;continue;
}
if(number == 1){
if(find(X) == find(Y+n)||find(X) == find(Y+2*n))ans++;
else {
fa[find(Y)] = find(X);
fa[find(Y+n)] = find(X+n);
fa[find(Y+2*n)] = find(X+2*n);
}
}
if(number == 2){
if(find(X) == find(Y)||find(X) == find(Y+2*n)){ans++;continue;}
fa[find(Y+n)] = find(X);
fa[find(Y+2*n)] = find(X+n);
fa[find(Y)] = find(X+2*n);
}
}
cout<<ans;
}