1. 程式人生 > >帶權並查集【洛谷P1196】

帶權並查集【洛谷P1196】

傳送門:https://www.luogu.org/problemnew/show/P1196#sub

大家都說並查集按秩合併並沒有用,所以我以後大概也不會寫按秩合併了。

而且帶權並查集,不能寫按秩合併好像!

普通的並查集只能維護在不在同一個集合,合併到同一個集合,但是帶權並查集就可以維護很多很多東西啦。

比如這個題目,我們就用帶權並查集維護隊伍的長度。還要維護字首和。

注意:帶權並查集的find函式不能隨便寫,因為每一次find都會壓縮路徑然後搞亂掉權值。

所以在需要的時候儘可能少的寫find,這就是我的理解吧。如果有不會的請指出來哈

下面上程式碼,我們維護字首和就完事了。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5+7;
int p[maxn],s[maxn];
int sum[maxn];
void init()
{
	for(int i=0;i<maxn;i++)
	{
		p[i] = i;
		s[i] = 1;
	}
} 
int find(int x)
{
	if(p[x]==x) return x;
	int f = find(p[x]);
	sum[x] += sum[p[x]];
	return p[x] = f;
}
void unite(int x,int y)
{
	x = find(x);
	y = find(y);
	if(x==y) return;
	p[x] = y;
	s[y] += s[x];
	s[x] = 0;
}
bool same(int x,int y)
{
	return find(x)==find(y);
}
int main()
{
	int T;
	cin>>T;
	init();
	while(T--)
	{
		char op;
		int x,y;
		cin>>op>>x>>y;
		int fx = find(x);
		int fy = find(y);
		if(op=='M')
		{
			sum[fx] += s[fy];
			p[fx] = fy;
			s[fy] += s[fx];
			s[fx] = 0;
		}
		else
		{
			if(fx!=fy)
			{
				cout<<-1<<endl;
			}
			else
			{
				cout<<abs(sum[x]-sum[y])-1<<endl;
			}
		}
	}
	return 0;
}