题目链接:https://www.luogu.org/problemnew/show/P1196
思路:
带权并查集。对每个结点,构造表示该结点的头结点,该结点距头结点的距离,该列的大小3个数组。
在合并过程中,要维护每个结点的权值,将x所在列的头结点接到y所在列的尾部,并修改xx距新头结点的距离,然后修改列的大小。
在查询过程中,也要维护每个结点的权值,计算两个结点的差值即可得到结果。
代码如下:
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 int t; 5 int f[30005],l[30005],s[30005]; 6 7 int get(int k){ 8 if(f[k]==k) return k; 9 else{ 10 int tmp=f[k]; 11 f[k]=get(f[k]); 12 l[k]+=l[tmp]; 13 s[k]=s[f[k]]; 14 return f[k]; 15 } 16 } 17 18 int main(){ 19 scanf("%d",&t); 20 for(int i=1;i<=30000;i++) 21 f[i]=i,l[i]=0,s[i]=1; 22 char m; 23 int x,y; 24 while(t--){ 25 scanf(" %c",&m); 26 scanf("%d%d",&x,&y); 27 int xx,yy; 28 if(m=='M'){ 29 xx=get(x); 30 yy=get(y); 31 f[xx]=yy; 32 l[xx]=s[yy]; 33 s[xx]+=s[yy]; 34 s[yy]=s[xx]; 35 } 36 else{ 37 xx=get(x); 38 yy=get(y); 39 if(xx!=yy) 40 printf("-1 "); 41 else 42 printf("%d ",abs(l[x]-l[y])-1); 43 } 44 } 45 return 0; 46 }