zoukankan      html  css  js  c++  java
  • 食物链(带权并查集)

    题目链接:http://poj.org/problem?id=1182

    题目:

    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

    思路:用一个3*N的数组来维护他们之间的关系,x+n为x的捕食者,x+2*n为x的猎物,因而当x与y的关系是同类的时候,需将他们+n、+2*n都一起合并为一个集合;当他们为捕食关系时,要将他们设为彼此的猎物。坑点为:不要用多组输入!!!
    代码实现如下:
     1 #include <cstdio>
     2 
     3 const int maxn = 5e4 + 7;
     4 int n, k, ans;
     5 int d, x, y;
     6 int fa[maxn * 3], r[maxn * 3];
     7 
     8 void init(int n) {
     9     for (int i = 0; i < n; i++) {
    10         fa[i] = i;
    11         r[i] = 0;
    12     }
    13 }
    14 
    15 int fi(int x) {
    16     return fa[x] == x ? x : fa[x] = fi(fa[x]);
    17 }
    18 
    19 void unite(int x, int y) {
    20     int p1 = fi(x), p2 = fi(y);
    21     if (p1 == p2) return;
    22     if (r[p1] > r[p2]) {
    23         fa[p2] = p1;
    24     } else {
    25         fa[p1] = p2;
    26         if (r[p1] == r[p2]) r[p2]++;
    27     }
    28 }
    29 
    30 bool check(int x, int y) {
    31     return fi(x) == fi(y);
    32 }
    33 
    34 int main() {
    35     scanf("%d%d", &n, &k);
    36     init(3 * n);
    37     ans = 0;
    38     for (int i = 0; i < k; i++) {
    39         scanf("%d%d%d", &d, &x, &y);
    40         x = x - 1, y = y - 1;
    41         if (x < 0 || x >= n || y < 0 || y >= n) {
    42             ans++;
    43             continue;
    44         }
    45         if (d == 1) {
    46             if (check(x, n + y) || check(x, 2 * n + y)) {
    47                 ans++;
    48             } else {
    49                 unite(x, y);
    50                 unite(n + x, n + y);
    51                 unite(2 * n + x, 2 * n + y);
    52             }
    53         } else {
    54             if (check(x, y) || check(x, y + 2 * n) || x == y) {
    55                 ans++;
    56             } else {
    57                 unite(x, n + y);
    58                 unite(x + n, y + 2 * n);
    59                 unite(x + 2 * n, y);
    60             }
    61         }
    62     }
    63     printf("%d
    ", ans);
    64     return 0;
    65 }
  • 相关阅读:
    数据库更改自增和主键
    修改MySQL的默认数据存储引擎
    tomcat密码的坑
    通过System.getProperties()获取系统参数
    Java语言开发的,直接解压即可使用软件
    一个javascript面试题
    为什么学习差
    IDEA设置
    java关键字
    IDEA快捷键
  • 原文地址:https://www.cnblogs.com/Dillonh/p/8972632.html
Copyright © 2011-2022 走看看