zoukankan      html  css  js  c++  java
  • poj 1182/codevs 1074 食物链

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

    http://codevs.cn/problem/1074/

    动物王国中有三类动物 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 Description

    第一行是两个整数N和K,以一个空格分隔。   

    以下K行每行是三个正整数D,X,Y,两数之间用一个空格隔开,其中 D 表示说法的种类。   

    若D=1,则表示X和Y是同类。   

    若D=2,则表示X吃Y。

     
    输出描述 Output Description

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

     
    样例输入 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

    提示

    输入文件  

     对7句话的分析 100 7

    1 101 1  假话

    2 1 2    真话

    2 2 3    真话

    2 3 3    假话

    1 1 3    假话

    2 3 1    真话

     1 5 5    真话

    NOI 2001 食物链(eat)

    某位大神的详细到不能再详细题解:http://blog.csdn.net/c0de4fun/article/details/7318642

    我就只简单说说吧

    基本思路:加权并查集

    第2、3种假话,特判。

    第1种:

    对于每一个节点,维护2个值,father:它的父节点;

    relation:子节点相对于父节点的关系(这句一定要记清楚)0表示同类、1表示被父节点吃、2表示吃父节点

    选定0,1,2及其代表含义的原因:

    输入x,y,对于y来说

    ①,题目中给出的d,如果d=1,d-1=0表示同类;如果d=2,d-1=1表示y被x吃

    ②,子节点相对于父节点的relation=0,那么父节点相对于子节点的relation=(3-0)%3=0,同类;

         子节点相对于父节点的relation=1,表示子节点被父节点吃,那么父节点相对于子节点的relation=3-1=2,表示父节点吃子节点;

         子节点相对于父节点的relation=2,将上面反过来。

    对于每个说法,如果给出的2个节点的父节点不在同一个集合中,就合并2棵子树,如果在同一个集合中,就判断是不是假话。

    合并2棵子树:

    我们这样定义:

    struct node
    {
          int father,relation;
    }r[50001];

    第1部分:是y的父节点相对于y的关系。前文中relation的定义是子节点相对于父节点的关系,所以第1部分=(3-r[y].relation)%3

    第2部分:是y相对于x的关系。如果d=1,那么第2部分=d-1=0,如果d=2,表示x吃y,d-1=1,y被x吃,那么第2部分=1

    第3部分:x相对于x的父节点的关系,即r[x].relation

    所以合并时relation更新表达式:r[y.father]].relation=(3-r[y].relation+d-1+r[x].relation)%3

    判断是不是假话:

    1、如果d=1,表示说法中的x,y是同类,那么如果r[x].relation!=r[y].relation,就是假话

    2、如果d=2,表示x吃y,那么y相对于x的关系就是1

    b:y相对于y的父节点的值,即r[y].relation

    c: x的父节点相对于x的值,即3-r[x].relation

    所以判断x吃y的说法是否正确:如果(r[y].relation+3-r[x],relation)%3!=1,就是假话。

    最后再说说路径压缩时relation的维护

    很明显,x相对于祖先的relation=x相对于x的父节点的relation+x的父节点相对于祖先的relation。

    所以路径压缩时,relation的维护:r[x].relation=r[x].relation+r[r[x].father].relation

    但这里要注意,直接在代码中写这一行是错误的,因为这一句代码是在查找祖先的递归回溯时完成的,执行这一句时,r[x].father已经被更新成祖先节点,所以要事先记录x在查找祖先节点之前的父节点,用这个值代替代码中的r[x].relation

    #include<cstdio>
    
    using namespace std;
    
    int n,k,ans;
    struct node
    {
        int relation,father;
    }e[50001];
    int d,x,y;
    
    int find(int i)
    {
        if(e[i].father!=i)
        {
            int tmp=e[i].father;
            e[i].father=find(tmp);
            e[i].relation=(e[i].relation+e[tmp].relation)%3;
        }
        return e[i].father; 
    }
    int main()
    {
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++) e[i].father=i;
        for(int i=1;i<=k;i++)
        {
            scanf("%d%d%d",&d,&x,&y);
            if(x>n||y>n) ans++;
            else if(d==2&&x==y) ans++;
            else
            {
                int r1=find(x);
                int r2=find(y);
                if(r1!=r2) 
                {
                    e[r2].father=r1;
                    e[r2].relation=(3-e[y].relation+(d-1)+e[x].relation)%3;
                }
                else
                {
                    if(d==1)
                      {
                            if(e[x].relation!=e[y].relation) ans++;
                      }
                    else
                      if((e[y].relation+3-e[x].relation)%3!=1) ans++;
                }
            }
        }
        printf("%d",ans);
    }

    这道题据说还可以用3个并查集来做

  • 相关阅读:
    K3s+Jetson Nano,在边缘端实现实时视频分析!
    15分钟连接Jetson Nano与K8S,轻松搭建机器学习集群
    配置高可用K3s集群完全攻略
    K3s+Sysdig,8分钟部署并保护集群安全!
    1款工具助力Rancher HA快速部署,极速提升研发测试效率
    连刷40道题,告别动态规划,谈谈我的经验
    直通BAT算法精讲视频教程分享
    关于三次握手和四次挥手,面试官想听到怎样的回答?
    Redisson 分布式锁实战与 watch dog 机制解读
    Spring 注解动态数据源设计实践
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/6294235.html
Copyright © 2011-2022 走看看