dreamxr
精诚所至,金石为开!

导航

 

分析

  并查集,需要维护集合内元素与根节点的关系(吃?被吃?同类)

  有点类似向量的想法

  如果x y属于同一集合

  

  

  如果x y不属于同一集合

 

  dis[x]=0表示x与根节点同类,1表示根节点吃x,2表示x吃根节点.

  

 1 #include<cstdio>
 2 #include<cstring>
 3 #define N 50010
 4 using namespace std;
 5 int root[N],dis[N],n,m;
 6 void init(){
 7     for(int i=1;i<=n;i++){
 8         root[i]=i;
 9         dis[i]=0;
10     }
11 }
12 int find(int x){
13     if(x==root[x])return x;
14     int rx=root[x];
15     root[x]=find(root[x]);
16     dis[x]=(dis[x]+dis[rx])%3;
17     return root[x];
18 }
19 int main(){
20     scanf("%d%d",&n,&m);
21         init();
22         int ans=0;
23         while(m--){
24             int d,x,y;
25             scanf("%d%d%d",&d,&x,&y);
26             if(x>n||y>n){
27                 ++ans;
28                 continue;
29             }
30             if(d==1){
31                 if(find(x)!=find(y)){
32                     dis[root[x]]=(dis[y]-dis[x]+3)%3;//注意这两句的更新顺序...
33                     root[root[x]]=root[y];
34                 }
35                 else{
36                     if((dis[y]-dis[x]+3)%3)
37                         ++ans;
38                 }
39             }
40             else{
41                 if(find(x)!=find(y)){
42                     dis[root[x]]=(dis[y]-dis[x]+4)%3;
43                     root[root[x]]=root[y];
44                 }
45                 else{
46                     if((dis[y]+1-dis[x]+3)%3)
47                         ++ans;
48                 }
49             }
50         }
51         printf("%d\n",ans);
52     
53     return 0;
54 }
posted on 2012-09-10 22:39  dreamxr  阅读(104)  评论(0编辑  收藏  举报