zoukankan      html  css  js  c++  java
  • POJ 1182 食物链(经典带权并查集 向量思维模式 很重要)

    传送门:

    http://poj.org/problem?id=1182

    食物链
    Time Limit: 1000MS   Memory Limit: 10000K
    Total Submissions: 90562   Accepted: 27216

    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

    Source

     
    分析:
    code:
    #include <iostream>
    #include<algorithm>
    #include <cstdio>
    #include<cstring>
    #include<math.h>
    #include<memory>
    using namespace std;
    typedef long long LL;
    #define max_v 50010
    int sum;
    struct node
    {
        int pre;//前驱
        int relation;//和前驱的关系
        //p[i].relation表示i的根结点到i的偏移量
    }p[max_v];
    void make_set(int x)
    {
        p[x].pre=x;//前驱默认自己
        p[x].relation=0;//关系默认0
    }
    int find_set(int x)
    {
        int temp;
        if(x==p[x].pre)
            return x;
        temp=p[x].pre;
        p[x].pre=find_set(temp);
        p[x].relation=(p[x].relation+p[temp].relation)%3;
        return p[x].pre;
    }
    void union_set(int a,int b,int k)
    {
        int root1=find_set(a);
        int root2=find_set(b);
        if(root1==root2)
        {
            if(k==1&&p[a].relation!=p[b].relation)
                sum++;
            if((k==2)&&((3-p[a].relation+p[b].relation)%3!=k-1))
                sum++;
            return ;
        }
    
        //合并
        p[root2].pre=root1;
        p[root2].relation=((k-1)+3+p[a].relation-p[b].relation)%3;
    }
    int main()
    {
        int n,m,a,b,k;
        scanf("%d %d",&n,&m);
    
        sum=0;//假话数目
    
        for(int i=1;i<=n;i++)
             make_set(i);
        for(int i=0;i<m;i++)
        {
            scanf("%d %d %d",&k,&a,&b);
            if(a>n||b>n)//假话
            {
                sum++;
                continue;
            }
            if(k==2&&a==b)//假话
            {
                sum++;
                continue;
            }
            union_set(a,b,k);//判断当前话是否跟前面说过的话冲突
        }
        printf("%d
    ",sum);
        return 0;
    }
     
  • 相关阅读:
    栈stack,queue队列
    安装Redis
    为什么负负得正,减负数的意义
    关于数组的记忆
    k8s环境常用操作
    conda python虚拟环境使用locust
    jmeter csv set data中sharing mode的使用说明
    redis常用操作
    数据库基准测试标准 TPC-C or TPC-H or TPC-DS
    influxdb基本操作
  • 原文地址:https://www.cnblogs.com/yinbiao/p/9432683.html
Copyright © 2011-2022 走看看