洛谷 P2024 食物链
作者:互联网
题目传送门:https://www.luogu.com.cn/problem/P2024
一般的并查集只能用来解决”亲戚的亲戚是亲戚“这类问题,但是如果关系变得复杂就不好解决。
比如”敌人的敌人是朋友“这类的问题,很明显普通的并查集无法解决,这个时候我们就要用到普通并查集的进阶版——种类并查集。
一般的种类并查集就是将数据范围扩大1倍,开一个2*n的数组,并将其分为两段,一段用来存放朋友,一段用来存放敌人。
本题存在三种关系,同类,猎物,天敌。所以仅仅开2*n的数组肯定不够,所以我们可以尝试开一个3*n的数组。
用1 ~ n来存同类,用n+1 ~ 2*n来存猎物,用2*n+1 ~ 3*n来存天敌。
对于一个数x来说,x为自己,x+n为猎物,x+2*n为天敌。
注意:如果对于x+n来说,x+n为自己,x+2*n为猎物,x为天敌。以此类推。
我们还要从题目中获取隐藏信息:
1、如x和y为同类,那么x+n和y+n为同类,x+2*n和y+2*n为同类。
2、如x吃y,那么x+n吃y+n,x+2*n吃y+2*n。
3、如x吃y,y吃z,那么z吃x。
了解了以上信息,ac本题就相当容易。
下面为ac代码:
#include <bits/stdc++.h> using namespace std; int fa[150010]; //普通并查集的板子 int find_x(int x) { if(x==fa[x]) return x; fa[x]=find_x(fa[x]); return fa[x]; } void add(int x,int y) { fa[find_x(x)]=find_x(y); } int main() { int n,q; cin>>n>>q; for(int i=1;i<=3*n;i++) //初始化 fa[i]=i; int sum=0; while(q--) { int s,x,y; cin>>s>>x>>y; if(x>n || y>n) //不在范围内 { sum++; continue; } if(s==1) //情况一 { if(find_x(x+n)==find_x(y) || find_x(x+2*n)==find_x(y)) //如果是捕食或被捕食的关系就是假话 { sum++; continue; } add(x,y),add(x+n,y+n),add(x+2*n,y+2*n); //如x和y为同类,那么x+n和y+n为同类,x+2*n和y+2*n为同类 } if(s==2) //情况二 { if(x==y) //不可能自己捕食自己 { sum++; continue; } if(find_x(x)==find_x(y) || find_x(x+2*n)==find_x(y)) //如果是同类或被捕食的关系就是假话 { sum++; continue; } add(x+n,y),add(x+2*n,y+n),add(x,y+2*n); //如x吃y,那么x+n吃y+n,x+2*n吃y+2*n } } cout<<sum; return 0; }
标签:P2024,洛谷,食物链,int,查集,同类,fa,add,find 来源: https://www.cnblogs.com/is-land/p/16470570.html