zoukankan      html  css  js  c++  java
  • 食物链

    北大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 */
  • 相关阅读:
    ....
    CodeForces 375A(同余)
    POJ 2377 Bad Cowtractors (最小生成树)
    POJ 1258 AgriNet (最小生成树)
    HDU 1016 Prime Ring Problem(全排列)
    HDU 4460 Friend Chains(bfs)
    POJ 2236 Wireless Network(并查集)
    POJ 2100 Graveyard Design(尺取)
    POJ 2110 Mountain Walking(二分/bfs)
    CodeForces 1059B Forgery(模拟)
  • 原文地址:https://www.cnblogs.com/zlyblog/p/2595796.html
Copyright © 2011-2022 走看看