1. 程式人生 > >再做食物鏈【擴充套件並查集】

再做食物鏈【擴充套件並查集】

這題很明顯總共有三種關係:

1、x與y同類

2、x吃y

3、y吃x

所以這時候,如果只有一個域就不能表示這3種關係了,比如將(x,y)合併,那麼這時候是x,y哪種關係呢? 所以這時候我們就要將這一個點擴充套件為3個點。 同類域,吃域,被吃域。

具體看程式碼吧:

#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
const int N = 50001;
int pre[N*3];
void init(int n)
{
	for(int i=0;i<=n*3;i++)
	{
		pre[i]=i;
	}
}
int find(int x)
{
	if(x==pre[x]) return x;
	else
	return pre[x]=find(pre[x]);
}
void Union(int x,int y)
{
	int rootx = find(x);
	int rooty = find(y);
	if(rootx!=rooty)
	{
		pre[rootx]=rooty;
	}
	return ;
}
int main()
{
	int n,k,x,y,op,ans;
	cin>>n>>k;
	
		ans=0;
		init(n);
		for(int i=0;i<k;i++)
		{
			cin>>op>>x>>y;
			if(x>n||y>n)
			{
				ans++;
				continue;
			}
			if(op==1)
			{
				if(find(x+n)==find(y) || find(x)==find(y+n))
				{
					ans++;
				}
				else{
					Union(x,y);
					Union(x+n,y+n);
					Union(x+2*n,y+2*n);
				}
			}
			if(op==2)
			{
				if(x==y)
				{
					ans++; continue;
				}
				if(find(x)==find(y)||find(y)==find(x+n))
				{
					ans++;
				}
				else{
					Union(x,y+n);
					Union(x+n,y+n+n);
					Union(x+2*n,y);
				}
			}
		}
		cout<<ans<<endl;
	
	return 0;
 }