洛谷 P1196 银河英雄传说

P1196 银河英雄传说

加权并查集,简介见加权并查集,具体方法见代码及注释

//P1196 银河英雄传说
#include<cstdio>
int fa[30010];
int r[30010];//r[i]表示第i号战舰在其父亲之后的第r[i]个位置
int r2[30010];//r2[i]表示以第i号战舰为队首的队列有r2[i]辆战舰
//本来只想到了记录战舰i后面的战舰数量,但是操作量太大,这里是受到其他人启发了 
int t;
int getans(int x,int y)//计算x与y之间战舰数量,"之间"指的就是不包括x和y本身
{
	if(x==y)
		return 0;
	if(x>y)
		return x-y-1;
	if(x<y)
		return y-x-1;
}
int find(int x)
{
	if(fa[x]==x)	return x;
	int t=find(fa[x]);
	r[x]+=r[fa[x]];//路径压缩,x在fa[x]之后的r[x]个位置,fa[x]在t之后的r[fa[x]]个位置,因此x在t之后的r[x]+r[fa[x]]个位置处
	fa[x]=t;
	return t;//返回根结点
}
void union1(int x,int y)
{
	int fx=find(x);
	int fy=find(y);
	fa[fx]=fy;//将x所在集合(fx)并入y所在集合(fy)
	r[fx]=r2[fy];//fx集合所有战舰前方战舰数量都增加,但是暂时只更新根结点
	r2[fy]+=r2[fx];//以fy为首的队列战舰数量增加fx集合的战舰数量
	//r2[fx]=0;//fx集合战舰数量归零(没有这一步也没有关系,因为没有队列分离操作,这个值不再起作用)
}
int main()
{
	int i,x,y,fx,fy;
	char c;
	scanf("%d",&t);
	for(i=1;i<=30000;i++)
	{
		fa[i]=i;
		r2[i]=1;
	}
	for(i=1;i<=t;i++)
	{
		scanf("\n%c%d%d",&c,&x,&y);
		if(c=='M')
			union1(x,y);
		else
		{
			fx=find(x);
			fy=find(y);
			if(fx!=fy)
				printf("-1\n");
			else
				printf("%d\n",getans(r[x],r[y]));
		}
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值