银河英雄传说
并查集 +瞎搞
思路
对于合并和查询是否存在于同一集合好说
关键就是查询之间的战舰数量的问题
可以利用树上前缀和的思想来实现
用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。