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;
}
原文地址:https://www.cnblogs.com/Idi0t-N3/p/13307707.html