poj 1988

一开始有n个木块在一行,有两种操作,第一种是把m所在的那一堆放到n所在的那一堆上面,第二种是查询木块m下面有多少个木块。
用并查集,将最底下的木块记录为根,则一个木块到最底下的距离就是该木块到根的距离。
如果连通分量a有2个木块,b有3个木块,则a的根到b的根的距离就是3,可知距离和当前连通分量的大小是有关的,因此要用一个数组记录。
查询时,有可能当前的根节点没更新过,所以要先更新路径

并查集的深入理解:并查集实质上就是森林,要把并查集往树的方向上多想想。

#include <cstdio>
#include <cstring>
using namespace std;
const int N = 30000 + 10 ;
int fa[N],son[N],n,x,y,dis[N];
int find(int x){
	if(x == fa[x]) {
		return x;
	}
	int tmp = fa[x];
	fa[x] = find(fa[x]);
	dis[x] += dis[tmp];
	return fa[x];
}
void Union(int x,int y){
	x = find(x); y = find(y);
	if(x != y){
		fa[x] = y;
		dis[x] = son[y];
		son[y] += son[x];
	}
}
char s[2];
int main(){
	while(~scanf("%d",&n)) {
		for(int i = 1;i<N;i++) fa[i] = i,son[i] = 1;
		memset(dis,0,sizeof(dis));
		for(int i = 0;i<n;i++){
			scanf("%s",s);
			if(s[0] == 'M') {
				scanf("%d%d",&x,&y);
				Union(x,y);
			}
			else {
				scanf("%d",&x);
				find(x) ;
				printf("%d\n",dis[x]);
			}
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/winhcc/article/details/89553765