题解 P1196 [NOI2002] 银河英雄传说

Posted 珂学的小萌新

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解 P1196 [NOI2002] 银河英雄传说相关的知识,希望对你有一定的参考价值。

题目分析:

带权并查集板子题,之前没有见过。

本题需要维护两个值,一个是是否联通,还有一个是每一艘船到当前队头的距离。

考虑在一般并查集的基础上额外维护两个值,一个是到队头的距离,另一个是当前整个队伍的长度,后者用来在合并时计算前者的。

更具体的:

合并时,将放在后面的队头的队头距离加上放在前面的队伍的长度并将两个队伍的长度合并。

查询的时候,记录下原来父节点的值,然后查询父节点,在路径压缩的时把自己到队头的距离加上父节点到队头的距离并更新所在的队伍长度。

关于最后一条的顺序问题,这是因为可能有多条路径等待压缩,需要先一次压完然后再加,而且加完后这个点就连到了根节点,也就不用担心会反复加了。


代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int T,fa[30005],front[30005],num[30005],x,y;
char c;
int find(int now){
	if(fa[now]==now)return now;
	int k=fa[now];
	fa[now]=find(fa[now]);
	front[now]+=front[k];
	num[now]=num[fa[now]];
	return fa[now];
}
int main(){
	scanf("%d",&T);
	for(int i=1;i<=30000;i++)
	fa[i]=i,num[i]=1;
	while(T--){
		cin>>c;
		if(c=='M'){
			scanf("%d%d",&x,&y);
			int fx=find(x),fy=find(y);
			fa[fx]=fy;
			front[fx]+=num[fy];
			num[fx]+=num[fy];
			num[fy]=num[fx];	
		}
		else{
			scanf("%d%d",&x,&y);
			if(find(x)!=find(y))printf("-1\\n");
			else 
			printf("%d\\n",abs(front[x]-front[y])-1);
		}
	}
	return 0;
}

以上是关于题解 P1196 [NOI2002] 银河英雄传说的主要内容,如果未能解决你的问题,请参考以下文章

做题记录:P1196 [NOI2002]银河英雄传说

P1196 [NOI2002] 银河英雄传说(并查集)

P1196 [NOI2002]银河英雄传说

P1196 [NOI2002]银河英雄传说

NOI2002 银河英雄传说(luogu p1196)

洛谷 P1196 [NOI2002]银河英雄传说