• 【POJ1182】 食物链 (带权并查集)


    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
    
    
    
    
    
    

    并查集距离大法好!!!

    若x->y 那么x到y距离为1(y到x距离为-1)

    若x--y 那么x到y距离为0

    那么mod 3相等就是不矛盾的。

    距离就是带权并查集维护。。

    话说我自Y的提根大法总是打错ORZZZZZ。。。

    就是合并x和y并查集的时候,可以先把x提到并查集的根,然后让y成为他的父亲。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<algorithm>
     6 #include<cmath>
     7 #include<vector>
     8 using namespace std;
     9 #define Maxn 50010
    10 
    11 int fa[Maxn],g[Maxn];
    12 
    13 int ffa(int x)
    14 {
    15     int now=fa[x];
    16     if(fa[x]!=x) fa[x]=ffa(fa[x]),g[x]=(g[x]+g[now])%3;
    17     return fa[x];
    18 }
    19 
    20 int mm(int x)
    21 {
    22     return (x%3+3)%3;
    23 }
    24 
    25 int main()    
    26 {
    27     int n,k;
    28     scanf("%d%d",&n,&k);
    29     for(int i=1;i<=n;i++) fa[i]=i,g[i]=0;
    30     int sum=0;
    31     for(int i=1;i<=k;i++)
    32     {
    33         int d,x,y;
    34         scanf("%d%d%d",&d,&x,&y);
    35         if(x>n||y>n) {sum++;continue;}
    36         if(d==1)
    37         {
    38             if(ffa(x)!=ffa(y))
    39             {
    40                 // fa[ffa(x)]=ffa(y);
    41                 int now=ffa(x);
    42                 fa[now]=x;g[now]=-g[x];
    43                 fa[x]=y;g[x]=0;
    44             }
    45             else
    46             {
    47                 if(mm(g[x])!=mm(g[y])) sum++;
    48             }
    49         }
    50         else
    51         {
    52             if(ffa(x)!=ffa(y))
    53             {
    54                 // fa[ffa(x)]=ffa(y);
    55                 int now=ffa(x);
    56                 fa[now]=x;g[now]=-g[x];
    57                 fa[x]=y;g[x]=1;
    58             }
    59             else
    60             {
    61                 if(mm(g[x]-g[y])!=1) sum++;
    62             }
    63         }
    64     }
    65     printf("%d
    ",sum);
    66     return 0;
    67 }
    View Code

    2016-11-11 22:04:38

  • 相关阅读:
    二维码生成:使用 JavaScript 库QRCode.js生成二维码
    VC++6.0远程调试(亲试成功)
    Linux同时安装python2和Python3
    Python打包-py2exe
    camera按键采集图像及waitKey的用法(转)
    ucos实时操作系统学习笔记——任务间通信(信号量)(转)
    STM32硬件IIC驱动设计(转)
    基于STM32F4移植W5500官方驱动库ioLibrary_Driver(转)
    USB基础知识概论(版本:v0.9.2)
    usb帧格式
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6055781.html
Copyright © 2020-2023  润新知