正题
题目链接:
https://www.luogu.org/problemnew/show/P1196
大意
有30000列和30000个飞船,开始时i号飞船在i列上。有两种操作:
(1)将x所在的列上的所有飞船连接在y号飞船所在的列上
(2)询问x号飞船与y号飞船之间相隔几个飞船
解题思路
用两个数组分别储存离它祖先的距离和后面的飞船数量(包括上自己)。然后在寻找祖先压缩路线时重新计算离他祖先的距离,然后用前缀和求相隔的飞船数。
代码
#include<cstdio>
using namespace std;
int father[30001],behind[30001],front[30001];
int n,q,x,y;
char c;
int abs(int x)
{
if (x<0) return -x;
else return x;
}
int find(int x)
{
if (father[x]==x) return x;
int lf=find(father[x]);
front[x]+=front[father[x]];//下传标记
return father[x]=lf;
}//寻找祖先
int unionn(int x,int y)
{
int fa=find(x),fb=find(y);
father[fa]=fb;
front[fa]=behind[fb];
behind[fb]+=behind[fa];
}//连接两点
int main()
{
scanf("%d",&q);
n=30000;
for (int i=1;i<=n;i++)
{
father[i]=i;
front[i]=0;
behind[i]=1;
}//初始化
for (int i=1;i<=q;i++)
{
scanf("\n%c %d %d",&c,&x,&y);
if (c=='M')
{
unionn(x,y);//连接
}
if (c=='C')
{
if (find(x)!=find(y)) printf("-1\n");
else
{
printf("%d\n",abs(front[x]-front[y])-1);//输出
}
}
}
}