• 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
  • 相关阅读:
    06文件操作
    内核层和用户层通讯的三种方式
    中断门
    工业控制网络安全技术与实践
    前言-anton安卓逆向的入门(零)
    前言与目录-白帽子讲Web安全(零)
    前言与目录-IDA Pro权威指南(零)
    前言与目录-C/C++常用算法手册(零)
    前言与目录-java常用算法手册(零)
    《想你的时候我和自己靠得很近》
  • 原文地址:https://www.cnblogs.com/zhixingr/p/6916793.html
Copyright © 2020-2023  润新知