题目
分析
很明显是需要维护信息的并查集
易错点
合并时候
习惯性地判断是否fx和fy相等,如果相等就不用再合并了
合并时注意方向
f[fx]=fy;
对d[fy]的赋值
不是赋值为1,而是要看fy的集合一共有多少元素,因为在此基础上,添加到末尾的
因此还要维护一个sum数组,根节点的下标对应的值为根节点所在集合的元素总数
d[]不能复制为1!!!!
因为如果d赋值为1
那么第二层节点在find时依旧会递归1次,那么d数组就会累加
d数组累加的次数和find的调用次数有关,因此两个点之间节点的数量就错了
因此d数组要初始化为0
最后小细节
两个节点中间的节点数是abs(d[x]-d[y])-1!!!记得减1
#include <bits/stdc++.h>
using namespace std;
const int N=30007;
int t;
int f[N],d[N];
int sum[N];
int find(int x)
{
if(f[x]==x) return f[x];
int t=find(f[x]);
d[x]=d[x]+d[f[x]];
f[x]=t;
return f[x];
}
int main()
{
//要维护信息了
//感觉第几列只是个幌子?
scanf("%d",&t);
for(int i=1;i<=30001;i++){
f[i]=i;
d[i]=0;
sum[i]=1;
}
for(int i=1;i<=t;i++){
char op[2];int x,y;
scanf("%s%d%d",op,&x,&y);
if(op[0]=='M'){
//第x号战舰所在的整个战舰队列,整体接到第y号战舰的尾部
int fx=find(x);int fy=find(y);
if(fx==fy) continue;
f[fx]=fy;
d[fx]=sum[fy];
sum[fy]+=sum[fx];
}else{
int fx=find(x);
int fy=find(y);
if(fx!=fy) printf("-1\n");
else printf("%d\n",abs(d[x]-d[y])-1);
}
}
return 0;
}