链接: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 }

 


 

 posted on 2014-04-12 15:10  莫扎特的代码  阅读(172)  评论(0编辑  收藏  举报