带权并查集 学习笔记

顾名思义,就是并查集带权值。
在路径压缩的时候,我们还要维护权值应该怎么办呢?

关联题目:P1196 [NOI2002] 银河英雄传说

我们对于一个舰队维护一个 \(fr\) 表示到头部的距离,\(cnt\) 表示该舰队的战舰数量。那么每一次合并时,先进行路径压缩,找到父亲,在将父亲的权值传下来即可。因为每一次合并都是从被合并的节点传下来,所以不会有重复。

如果还不明白的请看图:

image image

如图,我们将 \(4\) 所在的连通块合并到 \(3\) 所在的连通块,那么 \(\{4,5,6\}\) 会被合并到 \(1\) 的儿子,大小也根据 \(1\) 所在的连通块大小更新。但是这样的话我们就要控制 find() 函数的使用。

点击查看代码
int fa[maxn],fr[maxn],cnt[maxn];
int find(int x) {
	if(fa[x]==x) return x;
	int X=find(fa[x]);
	fr[x]+=fr[fa[x]];
	return fa[x]=X;
}
int T;
signed main() {
	For(i,1,30000) {
		fa[i]=i;
		fr[i]=0;
		cnt[i]=1;
	}
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	cin>>T;
	while(T--) {
		char ch;
		int x,y;
		cin>>ch>>x>>y;
		int X=find(x),Y=find(y);
		if(ch=='M') {
			fa[X]=Y;
			fr[X]+=cnt[Y];
			cnt[Y]+=cnt[X];
		} else {
			if(X!=Y) cout<< -1<<'\n';
			else cout<<abs(fr[x]-fr[y])-1<<'\n';
		}
	}
}
posted @ 2024-10-21 21:31  coding_goat_qwq  阅读(0)  评论(0编辑  收藏  举报