链接: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
...
用并查集维持这种关系
1 /************************************************************** 2 作者:陈新 3 邮箱:cx2pirate@gmail.com 4 用途:poj1182 5 时间:2014年 4月12日 15:00 6 测试:12745220 Will4944 1182 Accepted 548K 282MS C++ 967B 2014-04-12 14:58:49 7 *************************************************************/ 8 9 10 11 #include <stdio.h> 12 #define MAX_N 50005 13 14 int pre[MAX_N]; //并查集 15 int rel[MAX_N]; //与根节点关系 16 17 void init(); 18 int find(int u); 19 void unite(int r,int u,int v); 20 21 int main(){ 22 int m,n; 23 // while(scanf("%d%d",&m,&n) != EOF){ 我去!。。。。 24 scanf("%d%d",&m,&n); 25 int r,u,v,sum = 0; 26 init(); 27 for(int i = 0;i < n;i++){ 28 scanf("%d%d%d",&r,&u,&v); 29 if(u > m || v > m || (r == 2 && u == v)){ 30 sum++; 31 continue; 32 } 33 if(find(u) == find(v)){ 34 if((rel[u] - rel[v] + 4) % 3 != r){ 35 sum++; 36 } 37 } 38 else{ 39 unite(r,u,v); 40 } 41 } 42 43 printf("%d\n",sum); 44 // } 45 } 46 47 void init(){ 48 for(int i = 0;i < MAX_N;i++){ 49 pre[i] = i; 50 rel[i] = 1; 51 } 52 } 53 54 int find(int u){ 55 if(pre[u] == u){ 56 return u; 57 } 58 int t = find(pre[u]); 59 rel[u] = (rel[u] + rel[pre[u]] + 2) % 3; 60 pre[u] = t; 61 return pre[u]; 62 } 63 64 void unite(int r,int u,int v){ 65 int pu = find(u); 66 int pv = find(v); 67 pre[pu] = pv; 68 rel[pu] = (r + rel[v] - rel[u] + 3) % 3; 69 }