zoukankan      html  css  js  c++  java
  • POJ1703 Find them Catch them 关于分集合操作的正确性证明 种类并查集

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

    这道题和食物链那道题有异曲同工之处,都是要处理不同集合之间的关系,而并查集的功能是维护相同集合之间的关系。这道题中有两个不同的集合,朴素并查集只能查询两者是否属于同一个集合,扩展并查集可以建立多个集合之间的关系。

    本题我看了很多博客,对于两个集合,有许多博客都是采取2*n大小的并查集解决。大家的说法都是1-n属于一个集合,n-2*n属于另一个集合,我看的云里雾里,下面我想用我的方法来证明这样划分两个集合的正确性。

    证明:我们人为上的操作既然不会将k和n+k结点合并就说明k结点和n+k结点永远也不会在同一个集合中,我们可以认为(k,n+k)是一组对立元组,我们要将(a,b)元组中的a和b归到不同的集合中去,由于(a,n+a)和(b,n+b)一定是对立的元组,现在我们要制造(a,b)是对立元组的局面,我们可以知道(a,n+b)属于同一个集合和(a+n,b)属于同一个集合。现在不用管两个到底具体属于哪个集合,只要知道他们是属于不同的集合,所以只要将(a,n+b)合并还有(a+n,b)合并就可以保证(a,b)是对立元组。查询时也只要看(a,b)是否属于同一个集合。证毕。

    根据我的证明,大家应该对基础的种类并查集有了一点认识。代码如下:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4  
     5 using namespace std;
     6 const int maxn = 1e5 + 5;
     7  
     8 int n, m;
     9 int par[maxn*2], high[maxn*2];
    10  
    11 void init(int n)
    12 {
    13     for(int i = 1; i <= n; i++)
    14     {
    15         par[i] = i;
    16         high[i] = 0;
    17     }
    18 }
    19  
    20 int getRoot(int x)
    21 {
    22     return par[x] == x ? x : par[x] = getRoot(par[x]);
    23 }
    24  
    25 void unite(int x, int y)
    26 {
    27     x = getRoot(x);
    28     y = getRoot(y);
    29     if(x == y)    return;
    30  
    31     if(high[x] < high[y])    par[x] = y;
    32     else
    33     {
    34         par[y] = x;
    35         if(high[x] == high[y])    high[x]++;
    36     }
    37 }
    38  
    39 bool same(int x, int y)
    40 {
    41     return getRoot(x) == getRoot(y);
    42 }
    43  
    44 int main()
    45 {
    46     //freopen("in.txt", "r", stdin);
    47     int T;
    48     scanf("%d", &T);
    49     while(T--)
    50     {
    51         scanf("%d%d", &n, &m);
    52         init(2*n);
    53  
    54         char op;    int a, b;
    55         for(int i = 1; i <= m; i++)
    56         {
    57             scanf("
    %c%d%d", &op, &a, &b);
    58             if(op == 'D')
    59             {
    60                 unite(a, b+n);
    61                 unite(a+n, b);
    62             }
    63             else
    64             {
    65                 if(same(a, b+n) || same(a+n, b))    printf("In different gangs.
    ");
    66                 else if(same(a, b) || same(a+n, b+n))    printf("In the same gang.
    ");
    67                 else    printf("Not sure yet.
    ");
    68             }
    69         }
    70     }
    71     return 0;
    72 }
  • 相关阅读:
    性能监控工具之----PerfMon Metrics Collector
    idea 常用设置记录
    springboot 初体验之踩坑篇
    Interleave controller-jmeter
    js怎么判断一个类型是否为数组类型
    加载完成事件
    Jquery-查找
    Dom-增加、删除
    Dom-修改
    Dom-查找
  • 原文地址:https://www.cnblogs.com/randy-lo/p/12564943.html
Copyright © 2011-2022 走看看