食物链,洛谷之提高历练地,并查集

正文

      第二题:食物链

      这题经典啊!!!我们可以想象,如果我们可以搞一个并查集来维护x的同伙,天敌和食物就好了。

      我们想到了开三倍空间来维护x的天敌,同伙和食物。

      我们假设有一句话是x和y是同类,那么要满足两个条件,x不吃y,而且y不吃x。如果都满足,那么我们就可以把他们联系起来。

      我们再假设一句话是x吃y,那么要满足的条件显然有,x和y不为同类,而且y不吃x。

      我们再把他们联系起来即可。

      怎么联系呢?,我们看代码吧~

#include
#include
#include

int n,m;
int f[150010];//1<=i<=50000 1到50000表示i的同类,i+n表示i的食物,i+2*n为i的天敌。
int ans=0;

int findpa(int x){
	if(f[x]!=x) return f[x]=findpa(f[x]);
	return f[x];
}

bool comp(int x,int y){
	return findpa(x)==findpa(y);
}

void couple(int x,int y){
	if(findpa(x) != findpa(y)) f[findpa(x)]=findpa(y);
}

int main(){
	scanf("%d %d",&n,&m);
	for(int i=1;i<=3*n;i++)
		f[i]=i;
	for(int i=1;i<=m;i++){
		int k,x,y;
		scanf("%d %d %d",&k,&x,&y);
		if(k==2 && x==y || x>n || y>n){
			ans++;
			continue;	
		}
		if(k==1){
			if(comp(x,y+n) || comp(x+n,y)){//x不吃y,而且y不吃x。
				ans++;
				continue;
			}
			couple(x,y);
			couple(x+n,y+n);
			couple(x+2*n,y+2*n);
		}
		else{
			if(comp(x,y+n) || comp(x,y)){//x和y不为同类,而且y不吃x
				ans++;
				continue;			
			}
			couple(x,y+2*n);
			couple(x+n,y);
			couple(x+2*n,y+n);
		}
	}
	printf("%d\n",ans);
}

你可能感兴趣的:(食物链,洛谷之提高历练地,并查集)