vijos P1443 银河英雄传说

银河英雄传说

并查集 +瞎搞
思路
对于合并和查询是否存在于同一集合好说
关键就是查询之间的战舰数量的问题

可以利用树上前缀和的思想来实现
sum[i]表示i节点到根的距离
那么考虑维护
在A队接到B队的过程中 需要维护A的节点到根的距离
很显然A中所有节点的sum需要加上B中节点的个数
那就再开一个tot[i]表示i节点为根节点个数 
而且可以先不更新 在要用到A的子节点时再递归更新他们的sum
代码
#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

const int Maxn=30001;

char c;
int fa[Maxn],T,a,b,sum[Maxn],tot[Maxn];
int abs(int x){return x<0?-x:x;}
int find(int x)
{
	if(fa[x]==x)return x;
	int r=find(fa[x]);
	sum[x]+=sum[fa[x]];//递归处理距离
	fa[x]=r;
	return r;
}

int main()
{
	for(int i=1;i<=30000;i++){
		fa[i]=i;
		sum[i]=0;//根节点距离 
		tot[i]=1;//结点个数 
	}
	scanf("%d",&T);
	while(T--){
		scanf("\n%c",&c);
		if(c=='M'){
			scanf("%d%d",&a,&b);
			int r1=find(a);//寻找根节点 
			int r2=find(b);
			fa[r1]=r2;//相连 
			sum[r1]=tot[r2];//r1接到r2上 
			tot[r2]+=tot[r1];//r2的节点数加上r1的总节点数 
		}
		else{
			scanf("%d%d",&a,&b);
			int r1=find(a),r2=find(b);//寻找根节点 
			if(r1!=r2)printf("-1\n");
			else 
				printf("%d\n",abs(sum[a]-sum[b])-1);//计算距离 前缀和思想 
		}
	}
}


欢迎指出Bug

End。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值