zoukankan      html  css  js  c++  java
  • POJ 1182 食物链 (拆点并查集)

    食物链
    Time Limit: 1000MS   Memory Limit: 10000K
    Total Submissions: 78601   Accepted: 23422

    Description

    动物王国中有三类动物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),输出假话的总数。 

    Input

    第一行是两个整数N和K,以一个空格分隔。 
    以下K行每行是三个正整数 D,X,Y,两数之间用一个空格隔开,其中D表示说法的种类。 
    若D=1,则表示X和Y是同类。 
    若D=2,则表示X吃Y。

    Output

    只有一个整数,表示假话的数目。

    Sample Input

    100 7
    1 101 1 
    2 1 2
    2 2 3 
    2 3 3 
    1 1 3 
    2 3 1 
    1 5 5
    

    Sample Output:

    思路:
    拆点并查集,字面意思将一个点拆成数个点来进行并查集操作,比如a点拆成三个点变成a-x,a-y,a-z.分别代表属于不同的类,如果b和a是同一种族,那么就可以分别将a-x与b-x,a-y与b-y,a-z与b-z用并查集连接在一起,那么如果发现a-x和b-y,b-z相连那么肯定就和前面矛盾了,他们属于不同的类。没有关系不能连在一起。如果是捕食关系的话,因为该食物链组成了一个环,那么可以变成,x吃y,y吃z,z吃x。那么a,b之间的关系就有:a-x吃b-y,a-y吃b-z,a-z吃b-x.如果又不属于这个关系链的出现那么就矛盾了,假话+1.

    这个解释起来太麻烦了。。心态爆炸,实在说不来。。结合代码的话应该会好一些

    实现代码:

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int pre[50009*3];
    void init(int n){
        for(int i=0;i<=n;i++){
            pre[i] = i;
        }
    }
    
    int find(int x){
        if(x==pre[x])
            return x;
        int temp = pre[x];
        pre[x] = find(temp);
        return pre[x];
    }
    
    int same(int x,int y){
        int fx = find(x);int fy = find(y);
        if(fx == fy) return 1;
        else return 0;
    }
    
    void mix(int x,int y){
        int fx = find(x);int fy = find(y);
        pre[fx] = fy;
    }
    
    int main()
    {
        int n,m,ans,x,y,d;
        ans = 0;
       scanf("%d%d",&n,&m);
       init(3*n);
       while(m--){
          scanf("%d%d%d",&d,&x,&y);
          if(x<1||x>n||y<1||y>n){
            ans++;continue;
          }
          if(d==1){
              if(same(x,y+n)||same(x,y+n*2))
                ans++;
              else{
                mix(x,y);mix(x+n,y+n);mix(x+n*2,y+n*2);
              }
          }
          else{
            if(same(x,y)||same(x,y+2*n))  ans++;
            else{
                mix(x,y+n);mix(x+n,y+2*n);mix(x+2*n,y);
            }
          }
       }
       printf("%d",ans);
       return 0;
    }
    
    
  • 相关阅读:
    二分图最大匹配(匈牙利算法) POJ 3041 Asteroids
    贪心 FZU 2013 A short problem
    数学 FZU 2074 Number of methods
    莫队算法/二分查找 FZU 2072 Count
    畅通工程 HDU
    Minimum Inversion Number~hdu 1394
    I Hate It HDU
    A Simple Problem with Integers~POJ
    敌兵布阵
    Coins HDU
  • 原文地址:https://www.cnblogs.com/kls123/p/7810257.html
Copyright © 2011-2022 走看看