zoukankan      html  css  js  c++  java
  • poj 1182 食物链 带权并查集

    食物链是并查集的进阶运用的一道非常经典的题目。

    题目如下:

    动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形。A吃B, B吃C,C吃A。
    现有N个动物,以1-N编号。每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种。
    有人用两种说法对这N个动物所构成的食物链关系进行描述:
    第一种说法是"1 X Y",表示X和Y是同类。
    第二种说法是"2 X Y",表示X吃Y。
    此人对N个动物,用上述两种说法,一句接一句地说出K句话,这K句话有的是真的,有的是假的。当一句话满足下列三条之一时,这句话就是假话,否则就是真话。
    1) 当前的话与前面的某些真的话冲突,就是假话;
    2) 当前的话中X或Y比N大,就是假话;
    3) 当前的话表示X吃X,就是假话。
    你的任务是根据给定的N(1 <= N <= 50,000)和K句话(0 <= K <= 100,000),输出假话的总数。 

    题目的实质就是把给的N个动物划分到3个集合里去。最核心的在于需要实现父亲的父亲的父亲是同类。联想到取余操作。思路就出来了。

     1 #include<cstdio>
     2 using namespace std;
     3 const int MAXN=50010;
     4 int fa[MAXN];
     5 int rel[MAXN];   // 0代表同类,1代表吃fa[i],2代表被吃
     6 void _set(int n)
     7 {
     8     for(int i=1;i<=n;i++)
     9     {
    10         fa[i]=i;
    11         rel[i]=0;
    12     }
    13 }
    14 int _find(int k)
    15 {
    16 if(fa[k]!=k)
    17 {
    18     int t=fa[k];
    19     fa[k]=_find(fa[k]);
    20     rel[k]=(rel[k]+rel[t])%3;
    21 }
    22 return fa[k];
    23 }
    24 void _union(int x,int y,int d)
    25 {
    26     int fx=_find(x);
    27     fa[fx]=y;
    28     rel[fx]=(d-1-rel[x]+3)%3;
    29 }
    30 int relation(int x,int y,int root)
    31 {
    32     return (rel[x]-rel[y]+3)%3;
    33 }
    34 int main()
    35 {
    36    // freopen("in.txt","r",stdin);
    37    // freopen("out.txt","w",stdout);
    38     int n,d,x,y,fx,fy;
    39     long int k,ans;
    40     ans=0;
    41     scanf("%d %ld",&n,&k);
    42     _set(n);
    43     for(long int i=1;i<=k;i++)
    44     {
    45         scanf("%ld %ld %ld",&d,&x,&y);
    46         if(x>n||y>n)
    47         {
    48             ans++; //printf("1: %d %d %d
    ",d,x,y);
    49             continue;
    50 
    51         }
    52         if(d==2&&x==y)
    53         {
    54             ans++;
    55            // printf("2: %d %d %d
    ",d,x,y);
    56             continue;
    57 
    58         }
    59         fx=_find(x);
    60         fy=_find(y);
    61         if(fx!=fy)
    62         {
    63             _union(x,y,d);
    64         }
    65         else
    66         {
    67             if(d-1!=relation(x,y,fx))
    68             {
    69                 ans++;
    70               //  printf("3: %d %d %d %d
    ",d,x,y,relation(x,y,fx));
    71             }
    72         }
    73     }
    74     printf("%ld",ans);
    75     return 0;
    76 }
    View Code
  • 相关阅读:
    JAVA基础——编程练习(二)
    JAVA基础——面向对象三大特性:封装、继承、多态
    JVM内存
    50. Pow(x, n) (JAVA)
    47. Permutations II (JAVA)
    46. Permutations (JAVA)
    45. Jump Game II (JAVA)
    43. Multiply Strings (JAVA)
    42. Trapping Rain Water (JAVA)
    41. First Missing Positive (JAVA)
  • 原文地址:https://www.cnblogs.com/zhixingr/p/6916793.html
Copyright © 2011-2022 走看看