题目链接:https://www.acwing.com/problem/content/240/
题目给出初始时刻的n个队伍,每个队伍只有一个对应编号的i,操作有两种,一种是将第i列的接在第j列后面,一种是查询两个人是否在同一列,在同一列的话给出两者之间隔了多少人。
由于每一列都是一棵树,所以可以通过并查集进行求解,期间需要维护x到fx的距离,注意:每次fx改变的时候就要维护dx,并且需要一个辅助数组sizex在根节点计算树的大小。
代码:
#include<iostream> #include<cstdio> using namespace std; const int maxn = 30010; int f[maxn],siz[maxn]; int d[maxn];//d[x]表示的是x到fx的路径长度 int n; int find(int x){ if(x==f[x])return x; int root=find(f[x]); d[x]+=d[f[x]];//在没有路径压缩的情况下,d[x]表示的是指向前面结点的路径长度 return f[x]=root; } void merge(int x,int y){//将x拼接到y后面 int fx=find(x); int fy=find(y); if(x==y)return ; f[fx]=fy;//只有当fx改变的时候才改变d d[fx]=siz[fy]; siz[fy]+=siz[fx]; } int main(){ cin>>n; for(int i=1;i<=maxn-1;i++)f[i]=i,siz[i]=1; string s; int a,b; for(int i=1;i<=n;i++){ cin>>s>>a>>b; if(s[0]=='M')merge(a,b); if(s[0]=='C'){ if(find(a)==find(b))printf("%d ",abs(d[a]-d[b])-1); else puts("-1"); } } return 0; }