链接:http://poj.org/problem?id=1182
定义一种关系R(x,y),x > y 时 R(x,y) = 2;x = y 时 R(x,y)= 1;x < y 时 R(x,y) = 0
则R(x,y)有如下运算法则:
R(x,y) = (R(x,u) - R(y,u) + 4) % 3
R(x,y) = (R(x,u) + R(u,y) + 2) % 3
...
用并查集维持这种关系
/**************************************************************
作者:陈新
邮箱:cx2pirate@gmail.com
用途:poj1182
时间:2014年 4月12日 15:00
测试:12745220 Will4944 1182 Accepted 548K 282MS C++ 967B 2014-04-12 14:58:49
*************************************************************/
#include <stdio.h>
#define MAX_N 50005
int pre[MAX_N]; //并查集
int rel[MAX_N]; //与根节点关系
void init();
int find(int u);
void unite(int r,int u,int v);
int main(){
int m,n;
// while(scanf("%d%d",&m,&n) != EOF){ 我去!。。。。
scanf("%d%d",&m,&n);
int r,u,v,sum = 0;
init();
for(int i = 0;i < n;i++){
scanf("%d%d%d",&r,&u,&v);
if(u > m || v > m || (r == 2 && u == v)){
sum++;
continue;
}
if(find(u) == find(v)){
if((rel[u] - rel[v] + 4) % 3 != r){
sum++;
}
}
else{
unite(r,u,v);
}
}
printf("%d\n",sum);
// }
}
void init(){
for(int i = 0;i < MAX_N;i++){
pre[i] = i;
rel[i] = 1;
}
}
int find(int u){
if(pre[u] == u){
return u;
}
int t = find(pre[u]);
rel[u] = (rel[u] + rel[pre[u]] + 2) % 3;
pre[u] = t;
return pre[u];
}
void unite(int r,int u,int v){
int pu = find(u);
int pv = find(v);
pre[pu] = pv;
rel[pu] = (r + rel[v] - rel[u] + 3) % 3;
}