1. 程式人生 > >POJ 1988 Cube Stacking(並查集+路徑壓縮)

POJ 1988 Cube Stacking(並查集+路徑壓縮)

trac ref nio space == using n) scan 累加

題目鏈接:

id=1988">POJ 1988 Cube Stacking


並查集的題目


【題目大意】

有n個元素,開始每一個元素自己 一棧。有兩種操作,將含有元素x的棧放在含有y的棧的頂端,合並為一個棧。

另外一種操作是詢問含有x元素以下有多少個元素。

用sum數組儲存每一個棧中的元素個數。每次合並的時候將sum加到 父親節點。也就是每一個棧的最底部。

用under數組儲存當前節點以下有多少元素。每次合並的時候,就能夠將頂端元素的under賦值為父節點也就是棧最底部的sum。


void Union(int x,int y){
	int xr = find(x);
	int yr = find(y);
	if(xr==yr) return;
	father[xr]=yr;
	under[xr]=sum[yr];
	sum[yr]+=sum[xr];
}

在查詢的時候,運用遞歸的思想。從底部往上加under。

int find(int x){
	if(x==father[x])
		return father[x];
	int tmp = find(father[x]);
	under[x]+=under[father[x]]; //細致想想
	father[x]=tmp;
	return tmp;
}


【源碼】

#include <iostream> //父親節點在棧的底部
#include <cstdio>
using namespace std;
const int maxn = 30000+10;
int father[maxn];
int under[maxn];
int sum[maxn];
void init(){
	for(int i=0;i<maxn;i++){
		father[i]=i;
		under[i]=0;
		sum[i]=1;
	}
}
int find(int x){
	if(x==father[x])
		return father[x];
	int tmp = find(father[x]);
	under[x]+=under[father[x]];
	father[x]=tmp;
	return tmp;
}
void Union(int x,int y){
	int xr = find(x);
	int yr = find(y);
	if(xr==yr) return;
	father[xr]=yr;
	under[xr]=sum[yr];
	sum[yr]+=sum[xr]; 
}
int main(){
	int n;
	while(scanf("%d",&n)!=EOF){
		char ch;
		int a,b;
		init();
		for(int i=0;i<n;i++){
			scanf(" %c",&ch);
			if(ch=='M'){
				scanf("%d%d",&a,&b);
				Union(a,b);
			}
			else{
				scanf("%d",&a);
				int x=find(a); //僅僅是用來累加一下under
				printf("%d\n",under[a]);
			}
		}
	}
	return 0;
}



POJ 1988 Cube Stacking(並查集+路徑壓縮)