POJ 1988 Cube Stacking( 带权并查集 )*

POJ 1988 Cube Stacking( 带权并查集 )


**非常棒的一道题!借鉴“找回失去的”博客 **

**链接:****传送门 **

题意:

  • P次查询,每次查询有两种:
    1. M x y 将包含x的集合移动到y上面
    2. C x, 计算x下面有几个元素。用p[x]表示x的根结点,

思路:cnt[x] 表示x所在集合的元素个数,top[x] 表示x上面有几个元素。每次进行路径压缩时,top[x] 都要加上 top[ par[x] ],cnt 和 par 的操作就是并查集的基本操作。最后计算结果是用 x 所在集合元素的个数 - 在它之上的个数 - 它本身

balabala:这次修改在寻找 x 根节点和合并时更新两个维护数组非常棒,涨姿势了!


/*************************************************************************
    > File Name: poj1988.cpp
    > Author:    WArobot 
    > Blog:      http://www.cnblogs.com/WArobot/ 
    > Created Time: 2017年05月08日 星期一 22时27分30秒
 ************************************************************************/

#include<iostream>
#include<cstdio>
using namespace std;

const int maxn = 100000+10;
int n , par[maxn] , cnt[maxn] , top[maxn];	
// cnt[x]表示x集合的元素个数 
// top[x]表示x上面有几个元素每次路径压缩top[x]都要加上top[par[x]]
// 答案就是x所在集合的元素个数-在它之上的个数-本身
int find(int x){ 
	if( par[x] == x )	return x;
	else{
		int t = par[x];		// px记录一下现在x点父亲是谁
		par[x] = find(par[x]); 
		top[x] += top[t];	// 修正x的高度
		return par[x];
	}
}
void unite(int x,int y){
	int fx = find(x) , fy = find(y);
	if(fx!=fy){
		par[fy] = fx;
		top[fy] = cnt[fx];	// 将x集合放在y集合之上
		cnt[fx] += cnt[fy];
	}
}
int main(){
	int x,y;
	char op;
	while(~scanf("%d",&n)){
		for(int i=0;i<maxn;i++){
			par[i] = i , cnt[i] = 1 , top[i] = 0;
		}
		for(int i=0;i<n;i++){
			cin >> op >> x;
			if(op=='M'){
				scanf("%d",&y);
				unite(x,y);
			}
			else{
				int ans , nx;
				nx = find(x);
				ans = cnt[nx] - top[x] - 1;
				printf("%d\n",ans);
			}
		}
	}
	return 0;
}
posted @ 2017-05-09 00:53  ojnQ  阅读(170)  评论(0编辑  收藏  举报