zoukankan      html  css  js  c++  java
  • 带权并查集

    所谓带权并查集就是,在若干个集合之间需要做到维护一些信息,如相同,或者矛盾。

    POJ1182

    题意:

    动物王国中有三类动物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),输出假话的总数。

    解法:

    对于每只动物创建3个元素, i-A,i-B,i-C,并用这 3*N 个元素建立并查集,维护如下信息:

    1. i-X 表示“ i 属于种类 x”

    2. 并查集里的每一个组表示组内所有元素代表的情况都同时发生或者不发生。

    如果 i-A 和 j-B 在同一组里,就表示 i 属于种类 A 那么 j 一定属于种类 B。

    那么对于每一条信息我们只需要进行:

    第一种:x 和 y 是同一种,合并 x-A 和 y-A,x-B 和 y-B ,x-C 和 y-C

    第二种:x 吃 y,合并 x-A 和 y-B, x-B 和 y-C,x-C 和 y-A

    合并之前判断是否矛盾,如果给出的信息与我们要合并的内容矛盾,即更新答案。

     1 int p[3 * MAXN];
     2 int r[3 * MAXN];
     3 
     4 void init(int n) {
     5     for (int i = 1; i <= n; i++) {
     6         p[i] = i, r[i] = 0;
     7     }
     8 }
     9 
    10 int find(int x) { return p[x] == x ? x : p[x] = find(p[x]); }
    11 
    12 bool same(int x, int y) { return find(x) == find(y); }
    13 
    14 void unite(int x, int y) {
    15     x = find(x);
    16     y = find(y);
    17     if (x == y) return;
    18     if (r[x] < r[y]) {
    19         p[x] = y;
    20     } else {
    21         p[y] = x;
    22         if (r[x] == r[y]) r[x]++;
    23     }
    24 }
    25 
    26 int N, K;
    27 
    28 int main() {
    29     // freopen("input.txt", "r", stdin);
    30     cin >> N >> K;
    31     init(N * 3);
    32     int ans = 0;
    33     while (K--) {
    34         int id = READ(), x = READ(), y = READ();
    35         if (x < 1 || x > N || y < 1 || y > N) {
    36             ans++;
    37             continue;
    38         }
    39         if (id == 1) {
    40             if (same(x, y + N) || same(x, y + 2 * N)) {
    41                 ans++;
    42             } else {
    43                 unite(x, y);
    44                 unite(x + N, y + N);
    45                 unite(x + N + N, y + N + N);
    46             }
    47         } else {
    48             if (same(x, y) || same(x, y + 2 * N)) {
    49                 ans++;
    50             } else {
    51                 unite(x, y + N);
    52                 unite(x + N, y + N + N);
    53                 unite(x + N + N, y);
    54             }
    55         }
    56     }
    57     cout << ans << endl;
    58     return 0;
    59 }
  • 相关阅读:
    ASP.NET编程的十大技巧
    ADO.NET实用经验总结(5大对象访问数据库)
    一些讲C#3.0 的好文章收集
    新打开窗口,MD5加密,实体类方式保存在Session中,获得系统根路径,分页,动态获取XML数据到页面
    System.Drawing.Color.FromArgb(144,238,255);
    重要社区链接(资源技术网站)
    case when factsqy is NULL then '0' when factsqy is NOT NULL then factsqy end as factqtys
    了解Linq之前需要知道的一些概念
    sql left out join http://hi.baidu.com/llscompazz/blog/item/dc5e23d9ce2b62eb39012fb4.html
    正則表達式驗證通用方法
  • 原文地址:https://www.cnblogs.com/romaLzhih/p/11427324.html
Copyright © 2011-2022 走看看