poj 1182 --食物链(经典并查集)

119 阅读1分钟

题意:

题目不难看懂,但是做起来感觉很复杂。

思路:

种类并查集的应用,其中关键的几个公式推导感觉不是很好理解,以后回头看也许会有收获。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std; 
int p[50010],r[50010];
int n,k,co;
int find(int x){
	if(x!=p[x]){
		int fx=find(p[x]);
		r[x]=(r[x]+r[p[x]])%3;
		p[x]=fx;
	}
	return p[x];
}
bool uni(int d,int x,int y){
	int fx=find(x);
	int fy=find(y);
	if(fx==fy){
		if(((r[y]-r[x]+3)%3)!=d) return 1;
		else return 0;
	}
	p[fy]=fx;
	r[fy]=(r[x]-r[y]+3+d)%3;
	return 0;
}
void mem(){
	for(int i=1;i<=n;i++)
		p[i]=i;
	memset(r,0,sizeof(r));
} 
int main(){
	scanf("%d%d",&n,&k);
			int a,b,d;
			co=0;
			mem();
		for(int i=0;i<k;i++){
			scanf("%d%d%d",&d,&a,&b);
			if(a>n||b>n||(a==b&&d==2)){
				co++;continue; 
			}
			else if(uni(d-1,a,b)) co++;
			
		}
		printf("%d\n",co);
	
	return 0;
} 


\