POJ1182 食物链
/*关系并查集 kind[]
204MS 768K
*/
#include <stdio.h>
#include <string.h>
const int MAX=5*1e4+5;
int pa[MAX],kind[MAX];
void make_set(int N)//初始化节点
{
for (int k=1;k<=N;k++)
{
pa[k]=k;
kind[k]=0;
}
}
int find_set(int x)//查找父节点路径压缩
{
int tx,h=x,s1=0,s2;
while (h!=pa[h])
{
s1+=kind[h];
h=pa[h];
}
while (x!=pa[x])
{
tx=pa[x];
pa[x]=h;
s2=kind[x];
kind[x]=s1%3;
s1=s1-s2;
x=tx;
}
return h;
}
int union_set(int x,int y,int k)//合并集合
{
int tx=find_set(x);
int ty=find_set(y);
if (tx==ty)
{
if ((kind[x]-kind[y]+3)%3==k)//已有关系判断真假
return 0;
return 1;
}
pa[tx]=ty;
kind[tx]=(3-kind[x]+kind[y]+k)%3;//状态转移
return 0;
}
int main()
{
int N,K,sum=0,D,X,Y;
scanf ("%d%d",&N,&K);
make_set(N);
while (K--)
{
scanf ("%d%d%d",&D,&X,&Y);
if (X>N||Y>N) sum++;
else if (X==Y)
{
if (D==2)
sum++;
}
else sum+=union_set(X,Y,D-1);
}
printf ("%d\n",sum);
return 0;
}
//简单并查集模板
void make_set(int N)//初始化
{
for (int k=0;k<=N;k++)
pa[k]=k;
}
int find_set(int x)//寻找父亲节点并路径压缩
{
int tx,h=x;
while (h!=pa[h])
h=pa[h];
while (x!=pa[x])
{
tx=pa[x];
pa[x]=h;
x=tx;
}
return h;
}
void union_set(int x,int y)//合并集合
{
x=find_set(x);
y=find_set(y);
if (x==y) return ;
if (rand()&1) pa[x]=y;//打乱操作可不加
else pa[y]=x;
}