• 食物链


    北大oj1182

    rank[x]=

    0    表示节点x与father[x]为同类

    1    表示节点x吃father[x]

    2    表示x被father[x]吃

    向量的思考模式

    AB=rank[a],CB=rank[c];BC=-rank[c];  a与c的关系为rank[a]-rank[c];  

    判断两个节点点a, b的关系   

    . (1)如果ra != rb,说明a, b暂时没有关系,那么关于他们的判断都是正确的,然后合并这两个子树。这里是关键,如何合并两个子树使得合并后的新树能保证正确呢?( 将a所在的子树合并到b上)

    s表示 a与b的关系

      s=rank[a]+rank[f1]-rank[b]

      rank[f1]= s-rank[a]+rank[b]

     void union_set (int a,int b,int s)

     {

             int f1=find_set(a);

             int f2=find_set(b);

             father[f1]=rb;

             rank[f1]=(s - rank[a] + rank[b] + 3)%3;  

    }

    •(2)如果f1 =f2说明a, b之前已经有关系了。那么我们就判断语句是否是对的
    •同样根据向量的思考模式转化为
    • rank[a]-rank[b]==s 进行判断

       路径压缩:

         int find_set(int x)

         {

              int t;

              if(x==father[x]) return x;

             else {

              t=father[x];  father[x]=find_set(father[x]);

              rank[x]=(rank[x]+rank[t])%3;  (根据向量模式)

              return father[x];

              }

         }

              具体看代码

    View Code
     1 //食物链1182
     2 #include<stdio.h>
     3 int father[50001],rank[50001];
     4 int find(int x)
     5 {
     6     int t;
     7     if(father[x]==x)
     8         return x;
     9     else
    10     {
    11         t=father[x];
    12         
    13         father[x]=find(father[x]);
    14     rank[x]=(rank[x]+rank[t])%3;
    15     return father[x];
    16     }
    17 }
    18 void Union(int x,int y,int s)
    19 {
    20     int f1=find(x);
    21     int f2=find(y);
    22     father[f1]=f2;
    23     rank[f1]=(rank[y]-rank[x]+s+3)%3;
    24 }
    25 int main()
    26 {
    27     int n,m,s,x,y,f1,f2,i,j,num;
    28      scanf("%d%d",&n,&m);
    29 
    30         for(i=1;i<=n;i++)
    31         {
    32             father[i]=i;
    33             rank[i]=0;
    34         }
    35         num=0;
    36         for(j=1;j<=m;j++)
    37         {
    38             scanf("%d%d%d",&s,&x,&y);
    39             if(x>n||y>n||(s==2&&x==y))
    40                 num++;
    41             else
    42             {
    43                 f1=find(x);
    44                 f2=find(y);
    45                 if(f1==f2)
    46                 {
    47                     if((rank[x]-rank[y]+3)%3!=s-1)
    48                         num++;
    49                 }
    50                 else
    51             
    52                     Union(x,y,s-1);
    53             
    54             }
    55         }
    56             printf("%d\n",num);
    57         
    58 
    59     return 0;
    60 }
    61 /*
    62 100 7
    63 1 101 1 
    64 2 1 2
    65 2 2 3 
    66 2 3 3 
    67 1 1 3 
    68 2 3 1 
    69 1 5 5
    70 */
  • 相关阅读:
    20155327 2016-2017-3 《Java程序设计》第4周学习总结
    Hadoop常见错误解决
    正则表达式30分钟入门教程
    Java并发之CopyOnWriteArrayList
    web.xml加载顺序
    详解@Autowired、@Qualifier和@Required
    Java HashMap的死循环
    Redis学习手册(服务器管理)
    Redis介绍及常用命令
    Cron表达式
  • 原文地址:https://www.cnblogs.com/zlyblog/p/2595796.html
Copyright © 2020-2023  润新知