POJ 1182
重新做了一下这道并查集的题目,关键要点是抓住这种循环的关系和模运算的通性,进而利用加权并查集
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn = 5e4+3;
const int maxk = 1e5+3;
// tp 0: same 1: eat fa 2: eaten by fa
int tp[maxn], fa[maxn];
int Find(int x)
{
	if (x== fa[x]){
		return x;
	}
	int tf= fa[x];
	fa[x]= Find(tf);
	tp[x]= (tp[tf]+tp[x])%3;
	return fa[x];
}
void MakeSet(int n)
{
	for (int i= 1; i<= n; ++i){
		fa[i]= i;
	}
}
void Init(int n)
{
	memset(tp, 0, sizeof(tp));
	MakeSet(n);
}
int Union(int op, int a, int b)
{
	int pa= Find(a);
	int pb= Find(b);
	if (pa== pb){
		if (tp[a]== tp[b] && 1== op){
			return 1;
		}
		if ((1== ((3+tp[a]-tp[b])%3)) && 2== op){
			return 1;
		}
		return 0;
	}
	fa[pa]= pb;
	tp[pa]= (op-1+tp[b]+3-tp[a])%3;
	return 1;
}
int main()
{
	int n, k, ans= 0, op, x, y;
	scanf("%d %d", &n, &k);
	Init(n);
	for (int i= 0; i< k; ++i){
		scanf("%d %d %d", &op, &x, &y);
		if (x> n || y> n){
			++ans;
			continue;
		}
		if (!Union(op, x, y)){
			++ans;
		}
	}
	cout<<ans<<endl;
	return 0;
}

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号