zoukankan      html  css  js  c++  java
  • 种类并查集

    E - A Bug's Life POJ - 2492

    D - Find them Catch them

    E - 食物链 POJ - 1182

    种类并查集总归一个思想,就是把一堆的东西分为一些种类,但实际上,每个东西的种类并不确定,强行给它确定一个种类的会不好处理,因为它本身的不确定性。但是如果把他们归到一个集合里,有一个共同的根节点,当要判断某两个东西的关系时,就可以根据他们跟根节点的关系判断。就以食物链这题举例。

    题目大意就是,三类动物A吃B,B吃C,C吃A这么一个食物链,然后是有一堆动物并不确定他们是哪类动物,有个人说它们之间的关系,然后判断这个人说的假话有多少句。

    跟之前的思路,真话就它们归到一个根节点,而它们和根节点的关系有3种同类,吃,被吃,关键的处理就在于路径压缩以及和根节点的关系,还有判定是不是假话。假如就设定一个动物和它根节点的关系为,0跟根节点同类 1被根节点吃 2吃根节点,那么在路径压缩时,

    假如根节点是A,那么A<--B<--C,那么A<--C的关系是?通过观察可以发现00->0 01->1 02->2 10->1 11->2 12->0 20->2 21->0 22->1,C与A的关系是由C与B的关系还有B与A的关系决定的,在这个问题中就有,当前点与根节点关系=(当前点与目前的上一节点的关系+目前的上一节点与根节点关系)%3 。

    那在两个动物的根节点连接在一起时该怎么确定,其中一方跟根节点的关系呢?这就需要向量加法假设B是根节点是A,D的根节点的C,加入要把C连到A,C与A的关系就有

    A ← C      

    ↑      ↑     

    B ← D  

     其中D到B的关系是给出的0或1,代表D与B是同类或D被B吃,B与A,D与C的关系都确定,再要求C与A的关系,其实可以很直观的看出,就是C到D 的关系D到B的关系然后B到A的关系这样这个向量加法,所以A ← C就是C→D加D->B加B->A,D->C的关系逆过来就是C->D了。同样,若已经知道AB是同一根节点要判断是不是假话,也是可以利用向量加法。

     1 #include<stdio.h>
     2 struct Animal{
     3     int root,is;//0跟根节点同类 1被根节点吃 2吃根节点 
     4 }A[51108];
     5 int gui(int x);
     6 int bing(int z,int x,int y);
     7 int main()
     8 {
     9     int i,n,m;
    10     scanf("%d%d",&n,&m);
    11     for(i=1;i<=n;i++)
    12     {
    13         A[i].root=i;//根节点初始为自己 
    14         A[i].is=0;//自己是自己的同类 
    15     }
    16     int x,y,z,ans=0;
    17     while(m--)
    18     {
    19         scanf("%d%d%d",&z,&x,&y);
    20         if(x>n||y>n)
    21             ans++;
    22         else if(z==2&&x==y)
    23             ans++;
    24         else
    25             ans+=bing(z,x,y); 
    26     }
    27     printf("%d
    ",ans);
    28 }
    29 int gui(int x)
    30 {
    31     if(A[x].root==x)
    32         return x;
    33     int y=A[x].root,z=gui(A[x].root);//注意要先调整上一节点与根节点的关系再来调整
    34     A[x].is=(A[x].is+A[y].is)%3;//处理他们的关系 
    35     return A[x].root=z;
    36 }
    37 int bing(int z,int x,int y)
    38 {
    39     int bx=gui(x),by=gui(y);
    40     if(bx==by)//X和Y有公共根节点,代表之前有真话把他们联系在一起,此时方能判断真假 
    41     {
    42         if((A[y].is+3-A[x].is)%3!=z-1)//与公共根节点的关系判断话的真假 
    43             return 1;
    44     }//z-1就分别代表0 1 就xy同类还有y被x吃 
    45     else
    46     {
    47         A[by].root=bx;
    48         A[by].is=(A[x].is+3-A[y].is+z-1)%3;//向量加法 
    49     }
    50     return 0;
    51 }
  • 相关阅读:
    RHEL因为selinux设置失误,无法重启问题。(centos适用)
    Linux系统忘记管理员密码(CentOS、RHEL、Ubuntu)
    cobbler PXE 安装系统时出现的问题
    虚拟机ping 不通主机,主机可ping 虚拟机解决方法
    CentOS7系统更改网卡名为eth0
    PXE-cobbler 无人值守装机------续
    PXE-cobbler 无人值守装机
    DELL PowerEdge R410系统日志满报错
    matlab添加toolbox失败的解决办法
    vs2017+opencv3.4.0的配置方法
  • 原文地址:https://www.cnblogs.com/LMCC1108/p/9355380.html
Copyright © 2011-2022 走看看