洛谷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,按照吃的关系维护就好
当然这种方法我莫得代码

posted @ 2020-04-25 17:20  千载煜  阅读(119)  评论(0编辑  收藏  举报