POJ 1988 Cube Stacking(并查集+路径压缩)

题目链接:

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;
}
时间: 2024-12-25 19:21:43

POJ 1988 Cube Stacking(并查集+路径压缩)的相关文章

poj.1988.Cube Stacking(并查集)

Cube Stacking Time Limit:2000MS     Memory Limit:30000KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 1988 Description Farmer John and Betsy are playing a game with N (1 <= N <= 30,000)identical cubes labeled 1 through N. They st

POJ 1988 Cube Stacking

Cube Stacking Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 18820   Accepted: 6530 Case Time Limit: 1000MS Description Farmer John and Betsy are playing a game with N (1 <= N <= 30,000)identical cubes labeled 1 through N. They start w

POJ 1988 Cube Stacking(转)

这道题的思路,就是每次记下该点到父结点的个数,并记录下其下的结点个数.之后,每次"C"时,将总的减去它所压的方块,即答案!!!(也是参考别人的~-?) <pre name="code" class="cpp">#include<stdio.h> #include<iostream> using namespace std; #define max 30010 struct node { int parent;/

hdu 1558 线段相交+并查集路径压缩

Segment set Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3457    Accepted Submission(s): 1290 Problem Description A segment and all segments which are connected with it compose a segment set.

POJ 1988 Cube Stacking (带权并查集)

题目链接:http://poj.org/problem?id=1988 有n个元素,开始每个元素自己 一栈,有两种操作,将含有元素x的栈放在含有y的栈的顶端,合并为一个栈.第二种操作是询问含有x元素下面有多少个元素. 经典的带权并查集,cnt表示包含这个元素的集合中所有元素个数,dis表示这个元素离最上面元素的个数(距离). 看代码领会一下吧. 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio>

[POJ 1988] Cube Stacking (带值的并查集)

题目链接:http://poj.org/problem?id=1988 题目大意:给你N个方块,编号从1到N,有两种操作,第一种是M(x,y),意思是将x所在的堆放到y所在的堆上面. 第二种是C(x),意思是数x方块下面有多少个方块. 把两堆合成一堆,这个可以用并查集来实现,问题是,怎么样维护x方块下面有多少个方块呢? 先来分析一下题目,按照样例,我们有6个方块,1,2,3,4,5,6. 令Cnt(x) = C(x)+1. 先执行M(1,6),此时Cnt(1) = 2, Cnt(6) = 1 再

POJ 1988 Cube Stacking (带权并查集)

Farmer John and Betsy are playing a game with N (1 <= N <= 30,000)identical cubes labeled 1 through N. They start with N stacks, each containing a single cube. Farmer John asks Betsy to perform P (1<= P <= 100,000) operation. There are two typ

POJ 1988 Cube Stacking 【带权并查集】

<题目链接> 题目大意: 有几个stack,初始里面有一个cube.支持两种操作: 1.move x y: 将x所在的stack移动到y所在stack的顶部. 2.count x:数在x所在stack中,在x之下的cube的个数. 解题分析:由于要实现大量数的移动和归属关系,所以想到可能要用并查集,但是毫无疑问,普通的并查集不能够实现统计在x下的cube个数这一功能,所以我们通过带权并查集来实现,每一个stack,以最高的点为根,然后每一个点维护两个权值,它的子树节点个数(包括它自身),和它到

POJ 1988 Cube Stacking (种类并查集)

题目地址:POJ 1988 这道题的查找合并的方法都能想的到,就是一点没想到,我一直天真的以为查询的时候,输入后能马上输出,这样的话在合并的时候就要所有的结点值都要算出来,但是经过路径压缩之后,没办法全部都处理到,如果不压缩妥妥的TLE..于是看了看网上的题解.才发现自己是多么的天真(ben,四声)..在查询的时候只要找一次跟就可以了..这样不需查询的也就没必要处理出来.反而更省时. 这题的基本思路是很好想的.另开两个数组,一个记录以此节点为根的子节点的数目(这样合并的时候只需要加另一个根的数目