走你:http://poj.org/problem?id=1182
详情写在代码里了。有疑问请评论
#include <stdio.h>
#include <algorithm>
#include <string.h>
#define MAXN 50010
using namespace std;
int r[MAXN],k,lie,f[MAXN],n;
void init()
{
int i;
//printf("init is right\n");
for(i=1; i<=n; i++)
{
/*r[]表示每个节点与其对应的根节点之间的关系,
0表示同类
1表示被父节点吃
2表示吃父节点*/
f[i] = i; //父节点一开始全是自己
r[i] = 0; //自己跟自己一定是同类吧
}
}
int find_father(int x)
{
if(x == f[x])
return x;
int t= f[x]; //记录x的父节点
f[x] = find_father(f[x]); //找到X的祖宗节点
r[x] = (r[x]+r[t])%3; //更新 x 与父节点之间的关系
/*
我们假设 x 与 y的关系r1,y 与 z关系r2
x 与 z的关系为 (r1+r2)%3
*/
return f[x];
}
void uninon(int x,int y,int d)
{
int fx= find_father(x);
int fy= find_father(y);
f[fy]= fx;
r[fy]= (3-r[y]+(d-1)+r[x])%3;
/*fx为x的根,fy为y的根
合并时要把fx设置为fy的父节点
fy 对 y的关系为 (3-r[y])%3
y 对 x的关系为 d-1
x 对 fx 的关系 r[x]
所以fy 对应fx的关系为(3-r[y]+r[x]+d-1)%3
*/
}
int main()
{
scanf("%d %d",&n,&k);//带权并查集 这题 的坑点在这,他不用多组测试数据
init();
lie=0;
int op,x,y;
for(int i=0; i<k; i++)
{
//printf("lie is %d\n",lie);
scanf("%d %d %d",&op,&x,&y);
if(x>n||y>n||(op==2 && x==y))
lie++;
else if(find_father(x) == find_father(y))
{
if(op==1 && r[x]!=r[y] )
lie++;
if(op==2 && (r[x]+1)%3 !=r[y])
lie++;
}
else uninon(x,y,op);
}
printf("%d\n",lie);
return 0;
}