1. 程式人生 > >A Bug‘s life POJ 2492 解題報告 (種類並查集)

A Bug‘s life POJ 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;
}