poj 1988 Cube Stacking(加權並查集 )

相比無限種類並查集我更認爲這題是加權並查集(好吧種類並查集就是加權的一種,不要吐槽了~),這題也是我刷並查集專題的結束。以後博客如果再更並查集就是並查集的難題了233~不過希望我能解出並查集的難題並整理出題解分享給大家。。。

題意:就是說兩個農民A和B,面前有n(1<=n<=30000)個相同木塊(每個木塊都都序號1~n),移動p次(1<=p<=10,000)(次數比較多,我因爲這個寫的另外兩個算法超時了),A讓B移動木塊。有兩種操作
M x y 將包換 x的木塊移動到包含y的木塊上面。
C x 計算編號是x的 木塊下面有多少個木塊

思路: 並查集,把放在最下面的一個木塊認爲是根節點,然後其他放在上面的都用gp標記一下,表示下面有多少個木塊(gp[i]表示的是編號是i的木塊下面有多少個木塊),根節點的gp爲0,如果兩棵樹合併就用find的狀態壓縮,先遞歸,再維護(這個在前面幾個並查集裏詳細講了~),再用a數組存放這個以i爲根節點是樹中下一個葉子下面有多少個木塊,a數組初始化爲什麼爲1比較方便,可以模擬體會一下~

#include<cstdio>
#include<cstring>
#define LOCAL
using namespace std;
int gp[30100],pa[30100],max,min,a[30100];

inline void init(){
    for(int i = 0; i < 30050; i++){
        pa[i] = i;
        gp[i] = 0;
        a[i] = 1;
    } 
}

int find(int x){
    int fa;
    if(x != pa[x]){ 
       int tmp = pa[x];   
       pa[x] = find(pa[x]);
           gp[x] = gp[tmp] + gp[x];//維護樹,加權並查集的寫發
    }
    return pa[x];
}

void unite(int x,int y){
    int fx = find(x);
    int fy = find(y);
    if(fx != fy){
        pa[fx] = fy;
        gp[fx] = a[fy];
        a[fy] += a[fx]; 
    }
}

int main(){
/*#ifdef LOCAL
    freopen("in.txt","r",stdin);
#endif*/ 
    int p,x,y;
    char c;
    scanf("%d",&p);
    init();
    max = -1;
    min = 10010;
    while(p--){
        getchar();
        scanf("%c",&c);
        if(c=='C') {
            scanf("%d",&x);
            find(x);
            printf("%d\n",gp[x]);
        }
        else if(c=='M'){
            scanf("%d%d",&x,&y);
            unite(x,y);
        }
    }
    return 0;
}
發佈了37 篇原創文章 · 獲贊 7 · 訪問量 8718
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章