洛谷P2024食物链题解
这道题我们用带权并查集来搞
既然题目中有三种关系(同类,天敌,猎物),所以我们设定不同的距离来表示不同的关系。
设\(dis(x,y)=0\)表示\(x\)与\(y\)是同类,\(dis(x,y)=1\)表示\(x\)吃\(y\),在计算距离的时候%3,则\(dis(x,y)=2\)时,\(y\)吃\(x\)
在实现距离的时候,设\(dis[x]\)表示\(x\)到根的距离,\(dis(x,y)\)用\((dis[y]-dis[x]+3)%3\)来实现
这样在路径压缩的时候就要注意维护距离
具体看代码叭
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
int n,k,fa[50009],all,cnt,dis[50009];//dis[x]表示x到根的距离
int find(int x)
{
if(fa[x]==x) return x;
int xx=fa[x];
fa[x]=find(fa[x]);//先计算父亲的距离再搞这个点的距离
dis[x]=(dis[x]+dis[xx]+3)%3;
return fa[x];
}
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<=k;i++)
{
int opt,x,y;
scanf("%d%d%d",&opt,&x,&y);
if(x>n||y>n){all++;continue;}
int f1=find(x),f2=find(y);
if(opt==1)
{
if(f1!=f2)
{
dis[fa[x]]=(dis[y]-dis[x]+3)%3;
fa[fa[x]]=fa[y];
}
else
{
if(dis[x]!=dis[y]) all++;
}
}
if(opt==2)
{
if(f1!=f2)
{
dis[fa[y]]=(dis[x]-dis[y]+4)%3;
fa[fa[y]]=fa[x];
}
else
{
if(dis[y]!=(dis[x]+1)%3) all++;
}
}
}
printf("%d\n",all);
}
当然还有开三个并查集的神奇解法。
规定并查集1吃并查集2,并查集2吃并查集3,并查集3吃并查集1,按照吃的关系维护就好
当然这种方法我莫得代码