A Bug‘s life POJ 2492 解题报告 (种类并查集)

   看题链接:http://poj.org/problem?id=2492

   这也算是种类并查集的一道经典例题了吧,题意就不多解释了,先写一些我对种类并查集的一些理解。

   种类并查集比普通的并查集多一个relation数组,relation[i] 记录了 i 和 其直接父亲节点的关系,这个关系的表示因题目而异,种类并查集的重点和难点就是对这个relation数组的维护。种类

    在这个题中,relation数组具体表示是:以0表示和父亲节点的性别相同,1表示和父亲节点的性别不同。初始时可设初值全部为0。在Find函数中进行路径压缩时,要注意同时维护relation数组,如果relation[i] 和 relation[ father[i] ] 的值相同( 此时relation[ father[i] ] 实际上表示的是 i 的 父亲节点与 i 的祖先节点之间的关系)都是1 或者都是 0,可以推测出此时若将 i 链接到其祖先节点的话,relation[i] 应该变为0。若值不相同,则应变为1;

    在Union函数进行合并中,首先看看x 和 y是否在同一个集合中。如果在同一个集合中,那么再判断他们相较于祖先节点的关系,如果关系相同说明是同性恋。如果不在同一个集合里,就可以合并。合并之后要继续考虑这时relation数组的变化。在我们寻找变化规律之前,让我们再仔细的看看relation数组,如果你和我一样看过很多人的题解(汗……)你会发现很多人使用Rank数组来表示relation,其实这也是relation数组的本质,relation数组其实表示的正是节点的偏移量,不过不是递增或递减变化,而是0和1交替变化。如果明白了这一点,Union函数中的relation数组变化是不是就迎刃而解了呢?对!我们只要将两个节点的偏移量相减后再加一再%2,得到的就是新的偏移量。

    也正是如此,种类并查集其实是带偏移量的并查集。

     下面上一波C艹实现

#include <iostream>
#include <cstdio>


using namespace std;
const int MAXN = 2500;

int fa[MAXN], relation[MAXN];
bool flag;
void Init(int n){
    for(int i = 0;i <= n;++i){
        fa[i] = i;
        relation[i] = 0; 
    }
}

int Find(int x){
    if(fa[x] == x)
        return x;
    int temp = Find(fa[x]);
    relation[x] = (relation[x] + relation[fa[x]] ) % 2;
    fa[x] = temp;
    return temp;
}

void Union(int x, int y){
    int faX = Find(x), faY = Find(y);
    if(faX == faY){
        if(relation[x] == relation[y]){
            flag = true;
            return;
        }
    }
    fa[faX] = faY;
    relation[faX] = (relation[x] - relation[y] + 1 ) % 2; // 这里的+1其实可以认为是当faX连入faY时,x相对于faY的偏移量又加一。
}

int main()
{
    //freopen("input.txt", "r", stdin);
    int T;
    scanf("%d", &T);
    for(int i = 1;i <= T;++i){
        int n, k;
        flag = false;
        scanf("%d %d",&n, &k);
        Init(n);
        for(int i = 0;i < k;++i){
            int a, b;
            scanf("%d %d",&a, &b);
            if(flag)
                continue;
            Union(a, b);
        }
        printf("Scenario #%d:\n",i);
        if(flag)
            printf("Suspicious bugs found!\n");
        else
            printf("No suspicious bugs found!\n");
        printf("\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/aldo101/article/details/81084716