题目链接:https://vjudge.net/problem/POJ-1182
题解:x-0->y 表示x与y同类
x-1->y 表示x吃y
x-2->y 表示x被y吃
opt-1 表示关系
A[x].ra 表示x到根节点的权
fx 表示x的父亲
rootx 表示x的根
可得:a1-p->an = a1-p1->a2 + a2-p2->a3 + ... + a(n-1)-p(n-1)->an
p=(p1+p2+...+p(n-1))%3
合并:x->y = x->rootx + rootx->rooty + rooty->y
x->y=(opt-1) //根据代码理解opt-1
x->rootx=A[x].ra //根据代码理解A[x].ra
rooty->y=(3-A[y].ra)%3 根据代码理解A[y].ra
rootx->rooty = ((opt-1)-A[x].ra-(3-A[y].ra)%3+3)%3
寻根:x->rootx = x->fx + fx->root
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
int n,m;
struct node
{
int pre,ra;
node(int _pre=0,int _ra=0):pre(_pre),ra(_ra) {};
} A[50010];
int Find(int x)//寻根
{
if(x==A[x].pre) return x;
int tem=A[x].pre;
A[x].pre=Find(A[x].pre);
A[x].ra=(A[tem].ra+A[x].ra)%3;
return A[x].pre;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++) //初始化
A[i]=node(i,0);
int opt,x,y,ans=0;
for(int i=1; i<=m; i++)
{
scanf("%d%d%d",&opt,&x,&y);
if((x>n||y>n)||(opt==2&&x==y))//特判第二,三个条件
{
ans++;
continue;
}
int p1=Find(x),p2=Find(y);
if(p1!=p2)//合并
{
A[p1].pre=p2;
A[p1].ra=((opt-1)-A[x].ra-(3-A[y].ra)%3+3)%3;
}
else//如果不在同一个集合中才可以判断关系
{
if((opt-1)!=(A[x].ra+(3-A[y].ra)%3)%3) ans++;
}
}
printf("%d\n",ans);
}