POJ-1988-Cube Stacking-并查集

Cube Stacking

题目

Description

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 types of operations:
moves and counts.

  • In a move operation, Farmer John asks Bessie to move the stack containing cube X on top of the stack containing cube Y.
  • In a count operation, Farmer John asks Bessie to count the number of cubes on the stack with cube X that are under the cube X and report that value.
    Write a program that can verify the results of the game.

Input

  • Line 1: A single integer, P * Lines 2…P+1: Each of these lines describes a legal operation. Line 2 describes the first operation, etc. Each line begins with a ‘M’ for a move operation or a ‘C’ for a count operation. For move operations, the line also contains two integers: X and Y.For count operations, the line also contains a single integer: X.
    Note that the value for N does not appear in the input file. No move operation will request a move a stack onto itself.

Output

Print the output from each of the count operations in the same order as the input file.
Sample Input

6
M 1 6
C 1
M 2 4
M 2 6
C 3
C 4

Sample Output

1
0
2

题目链接POJ-1988-Cube Stacking

解题思路

POJ 的题真的是对小白选手的一个大的磨炼了,看了好久才明白题意,然后发现还是不会写题意就是**给你一个数n,然后又n次操作,每次操作有两种情况如果第一个字符是 M 那么就是把含 y 的队伍放在含 x 队伍下面,如果是 C 的话就输出 x 下面有几个数 ** 这个题真的是很妙呀!把递归和并查集完美的结合在一起的,我们需要先设置三个数组分别 用于 1,找该节点的父节点,2该节点到其祖先节点的距离,3以该节点为祖先节点的点有几个;每次查找然后更新一旦遇到C,就用该节点的祖先节点包含的点数减去这个点到其祖先节点的数量就可以啦,但是如何实施就是很关键有点点困难了!不过递归加回溯却刚好可以解决这个问题真的太舒服了,这个操作真是6呀!

#include<string.h>
#include<stdio.h>
#include<algorithm>

using namespace std;

int fa[30500];// 存节点 
int a[30500];// 以该节点为父节点的节点一共有几个 
int b[30200];//  该节点到其父节点的距离 

int find(int x)
{// 整个程序的核心算法 递归用的真是666666 
	if(fa[x]!=x)
	{
		int s=fa[x];// 将其上一个节点的值付给s 
		fa[x]=find(fa[x]);
		a[x]+=a[s];//x到其祖先节点的值等于他到他父节点的值加
				  //上起父节点到其祖先节点的距离 
	}
	return fa[x];
}

void jion(int x,int y)
{
	int xx=find(x);
	int yy=find(y);
	if(xx!=yy)
	{
		fa[yy]=xx;
		a[yy]+=b[xx];//因为把yy的父节点接到xx的父节点后面了 
		b[xx]+=b[yy];//所以yy到最终祖先节点的距离等于他到本来的祖先的距离 
	}  //加上xx到其祖先节点的距离,此时新的祖先节点的子孙 
}	//数量等于 以前 xx 的子孙加上 yy 的祖孙; 

int main()
{
	int n,x,y;
	char c;
	while(~scanf("%d",&n))
	{
		for(int i=1;i<=30009;i++)
		{
			a[i]=0;//自己到自己的距离为0;
			b[i]=1;//刚开始的时候每个节点都是一个祖先节点包含自己所以为1;
			fa[i]=i;//第i个值为自己方便以后找祖先节点
		}
		while(n--)
		{
			scanf(" %c",&c);
			if(c=='M')
			{
				scanf("%d%d",&x,&y);
				jion(x,y);
			}
			else {
				scanf("%d",&x);
				int s=find(x);//查找 x的祖先节点 
				printf("%d\n",b[s]-a[x]-1);
			}//  x 下面的节点等于总结点数减去x到祖先节点的个数 
		}
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值