• POJ-1182-食物链(并查集种类)


    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

    3


    思路:很明显的种类并查集。需要分三种。用虚拟节点做,开三倍pre[]。别的和两种的大同小异。

    坑点:如果没理解透虚拟节点是如何运行的,在判断 “当前的话与前面的某些真的话冲突,就是假话” 时可能会直接写if(!same(X,Y))

    merge(X,Y+2*N);模型上是建立了X 与 Y+2*N的同类关系,并且(虚拟)建立了X吃Y的关系。


    #include<cstdio>
    using namespace std;
    int N,K;
    int pre[150005];
    
    int find(int x){
        while(pre[x]!=x){
            int r=pre[x];
            pre[x]=pre[r];
            x=r;        
        }
        return x;
    }
    
    void merge(int x,int y){
        int fx=find(x);
        int fy=find(y);
        if(fx!=fy) pre[fx]=fy;
    }
    
    int same(int x,int y){
        return find(x)==find(y);
    }
    
    int main(){
        int D,X,Y;
        scanf("%d%d",&N,&K);
        
        for(int i=1;i<=3*N;i++)
            pre[i]=i;
        int ans=0;     
        while(K--){
            scanf("%d%d%d",&D,&X,&Y);
            if(X>N||Y>N){ ans++; continue; }
            
            if(D==1){
                if(same(X,Y+N)||same(X,Y+2*N)){ ans++; continue; } 
                merge(X,Y);
                merge(X+N,Y+N);
                merge(X+2*N,Y+2*N);
            }
            else{
                if(same(X,Y)||same(X,Y+N)){ ans++; continue; }    
                merge(X,Y+N*2);
                merge(X+N,Y);
                merge(X+2*N,Y+N);            
            }
        }
        printf("%d",ans);    
        return 0;
    }
  • 相关阅读:
    node.js入门(二) 第一个程序 Hello World
    node.js 入门(一)安装
    Windows平台字符的存储和输出分析
    设定MS SQL Server 2008定期自动备份
    OpenCV学习笔记(一)安装及运行第一个OpenCV程序
    Emgu学习笔记(一)安装及运行Sample
    vue脚手架 build-config文件夹(跨域/打包)相关配置
    fetch下载文件--统一拦截导出文件(含JAVA)
    git 避免重复输入密码
    form serialize获取不到上传文件数据解决办法
  • 原文地址:https://www.cnblogs.com/yzhhh/p/9960548.html
Copyright © 2020-2023  润新知