• POJ 1182 食物链 (并查集)


    食物链
    Time Limit: 1000MS   Memory Limit: 10000K
    Total Submissions: 50601   Accepted: 14786

    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




    草泥马我终于把这题A了!!!!!!
    当时我看完c primer plus的时候,心中最大的感觉就是真正优秀的教材就是能让傻子都能学懂,依照这样的观念来看———网上的大部分题解写得TM就跟屎一样!!!写不清楚你至少别误人子弟,推个公式推半天结果全是找规律没任何数学证明,乱七八糟写一堆浪费别人时间,要不是找到了那篇思路清晰的不知道还要耗几天!

    良心声明:我没精力也没本事把这题讲清楚,下面的过程纯属自用,留着以后自己来看,所以只求我自己能看懂,不建议参考,但是强烈推荐参考这篇: http://blog.csdn.net/niushuai666/article/details/6981689,清晰的说明了网上那堆乱七八糟的公式是如何用数学推出来的!



    R[i]的意思是 i的父节点 -> i 的关系,绝对不能反。

    STEP 1:
    
    
    这一步要先将x的父节点更新成最上面这个,然后再更新R[x]的值。


    STEP 2:

    所以要将右子树挂到左子树上去,那么右子树的根节点的关系值就要更新成它与左子树根节点的关系,从第二个图上可以看出来,新的R[fy] =(R[x] + v + (3 - R[y])) % 3,最后模3是为了确保关系值始终在0-2的范围内。


     1 #include <iostream>
     2 #include <cstdio>
     3 #include <string>
     4 #include <queue>
     5 #include <vector>
     6 #include <map>
     7 #include <algorithm>
     8 #include <cstring>
     9 #include <cctype>
    10 #include <cstdlib>
    11 #include <cmath>
    12 #include <ctime>
    13 using    namespace    std;
    14 
    15 const    int    SIZE = 50005;
    16 int    FATHER[SIZE],R[SIZE];
    17 int    N,M,ANS;
    18 
    19 void    ini(void);
    20 int    find_father(int);
    21 void    unite(int,int,int);
    22 int    main(void)
    23 {
    24     int    x,y,v;
    25 
    26     scanf("%d%d",&N,&M);
    27     ini();
    28     while(M --)
    29     {
    30         scanf("%d%d%d",&v,&x,&y);
    31         if(x > N || y > N || (x == y && v == 2))
    32             ANS ++;
    33         else
    34             unite(x,y,v);
    35     }
    36     printf("%d
    ",ANS);
    37 
    38     return    0;
    39 }
    40 
    41 void    ini(void)
    42 {
    43     ANS = 0;
    44     for(int i = 1;i <= N;i ++)
    45     {
    46         FATHER[i] = i;
    47         R[i] = 0;
    48     }
    49 }
    50 
    51 int    find_father(int n)
    52 {
    53     if(n == FATHER[n])
    54         return    n;
    55     int    temp = FATHER[n];
    56     FATHER[n] = find_father(FATHER[n]);
    57     R[n] = (R[temp] + R[n]) % 3;
    58 
    59     return    FATHER[n];
    60 }
    61 
    62 void    unite(int x,int y,int v)
    63 {
    64     int    fx = find_father(x);
    65     int    fy = find_father(y);
    66 
    67     if(fx == fy)
    68     {
    69         if((3 - R[x] + R[y]) % 3 != v - 1)
    70             ANS ++;
    71         return    ;
    72     }
    73 
    74     FATHER[fy] = fx;
    75     R[fy] = (R[x] + v - 1 + 3 - R[y]) % 3;
    76 }
     
  • 相关阅读:
    常用排序算法(JAVA版)
    常用排序算法(PHP)
    POJ 1308 hdu 1325 Is It A Tree?【并查集+入度 判断一个有向图是树】
    【转】常用的正则表达式
    POJ 1611 The Suspects【并查集入门】
    POJ 2524 Ubiquitous Religions【并查集入门】
    归并排序和快速排序比较【算法设计与分析实验报告】
    2013_CSUST_3_23校内训练赛第一场【old】【hdu 3496、2191、4508、4506、2181 POJ 3264 3210 3094】
    POJ 3264 Balanced Lineup 【RMQ求区间最值模板题】
    搜索专题训练【CSUST_Newer_12级入门】
  • 原文地址:https://www.cnblogs.com/xz816111/p/4538466.html
Copyright © 2020-2023  润新知