洛谷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
",all);
}

当然还有开三个并查集的神奇解法。
规定并查集1吃并查集2,并查集2吃并查集3,并查集3吃并查集1,按照吃的关系维护就好
当然这种方法我莫得代码

原文地址:https://www.cnblogs.com/lcez56jsy/p/12774053.html