题意: 有30000条队列,初始每条队列一条战舰,编号为1-30000,给出T条指令,分为合并和询问,合并指令为: M i j 含义为第i号战舰所在的整个战舰队列,作为一个整体(头在前尾在后)接至第j号战舰所在的战舰队列的尾部。询问指令为: C i j 该指令意思是,询问电脑,第i号战舰与第j号战舰当前是否在同一列中,如果在同一列中,那么它们之间布置有多少战舰。
分析: 我们发现,这里最难处理的就是要保存战舰之间的距离,其实想一想,战舰之间的距离不就是两者到这个队列最前面战舰的距离差么?这不就是一个带边权的并查集么?那么,我们通过修改find()操作即可查询距离。合并时怎么保证快速更新距离呢?新生成的边边权多少?其实就是第j号战舰所在的战舰队列的总数量,我们用一个num数组维护就可以了!
详细代码如下:
#include <bits/stdc++.h>
using namespace std;
int front[30010],fa[30010],num[30010];
int read() {
int ans=0,flag=1;
char ch=getchar();
while((ch>'9' || ch<'0') && ch!='-') ch=getchar();
if(ch=='-') flag=-1,ch=getchar();
while(ch>='0' && ch<='9') ans=ans*10+ch-'0',ch=getchar();
return ans*flag;
}
int find(int x) {
if(x!=fa[x]) {
int temp=fa[x];
fa[x]=find(fa[x]);
front[x]+=front[temp];
}
return fa[x];
}
int main() {
int t=read();
for(int i=1;i<=30000;i++) {
fa[i]=i;
num[i]=1;
front[i]=0;
}
for(int i=1;i<=t;i++) {
char ch=getchar();
int x=read(),y=read();
int fx=find(x),fy=find(y);
if(ch=='M') {
fa[fy]=fx;//增加一条边
front[fy]=num[fx];//边权
num[fx]+=num[fy];//维护num数组
num[fy]=0;
}else {
if(fx==fy) {
printf("%d\n",abs(front[x]-front[y])-1);
}else {
printf("-1\n");
}
}
}
return 0;
}
by:Chlience