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("\n%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.\n");
66                 else if(same(a, b) || same(a+n, b+n))    printf("In the same gang.\n");
67                 else    printf("Not sure yet.\n");
68             }
69         }
70     }
71     return 0;
72 }

猜你喜欢

转载自www.cnblogs.com/randy-lo/p/12564943.html