重新做了一下这道并查集的题目,关键要点是抓住这种循环的关系和模运算的通性,进而利用加权并查集
#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;
}