POJ1182 食物链 【并查集变种】

挺简单的

N个元素扩展为 3*N个

i-A i-B i-C

A吃B吃C吃A

挑战程序设计的89面

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
int N,K;
const int MAX_N=333333;
//并查集
int par[MAX_N];
int rank[MAX_N];//树的高度
void init(int n)
{
	for(int i=0;i<n;i++)
	{
		par[i]=i;
		rank[i]=0;
	}
}
int find(int x)//
{
		if(par[x]==x)
			return x;
		else
			return par[x]=find(par[x]);
}
//合并x和y所属的集合
void unite(int x,int y)
{
	x=find(x);
	y=find(y);
	if(x==y)
		return;
	if(rank[x]<rank[y])
		par[x]=y;
	else
	{
		par[y]=x;
		if(rank[x]==rank[y])
			rank[x]++;
	}
}
//推断x和y是否同属于一个集合
bool same(int x, int y)
{
	return find(x)==find(y);
}
int main()
{
	#ifndef ONLINE_JUDGE
		freopen("G:/1.txt","r",stdin);
		freopen("G:/2.txt","w",stdout);
	#endif
    scanf("%d%d",&N,&K);
	init(3*N);
	int kind,a,b;
	int ans=0;
	for(int i=0;i<K;i++)
	{
		scanf("%d%d%d",&kind,&a,&b);
		int x=a-1;
		int y=b-1;
		if(x<0||x>=N||y<0||y>=N)
		{
			ans++;
			continue;
		}
		if(kind==1)
		{
			if(same(x,y+N)||same(x,y+2*N))
			{
				ans++;
				continue;
			}
			unite(x,y);
			unite(x+N,y+N);
			unite(x+2*N,y+2*N);
		}
		else
		{
			if(same(x,y)||same(x+N,y+N)||same(x+2*N,y+2*N)||same(x,y+2*N))
			{
				ans++;
				continue;
			}
			unite(x,y+N);
			unite(x+N,y+2*N);
			unite(x+2*N,y);
		}
	}
	printf("%d\n",ans);
	return 0;
}


 

你可能感兴趣的:(poj)