有特殊意义的一道题……
加权并查集,我们增加cnt、deep数组
分别表示i点所在链共有多少个点,以及路径压缩之前点i在链中的深度
每次合并时直接修改cnt,路径压缩的同时更新deep
因为每次查询之前都要find,所以查询节点x的deep也就在找father时更新了
(deep数组初始化为零比较方便)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 5 using namespace std; 6 const int n=30000; 7 int father[n+10],deep[n+10],cnt[n+10]; 8 char c[10]; 9 10 void pre(){ 11 for (int i=1;i<=n;i++){ 12 deep[i]=0;//** 13 father[i]=i; 14 cnt[i]=1; 15 } 16 } 17 18 int find(int x){ 19 if (father[x]!=x){ 20 int fa=find(father[x]); 21 deep[x]+=deep[father[x]]; 22 father[x]=fa; 23 } 24 return father[x]; 25 } 26 27 void merge(int x,int y){ 28 int r1=find(x); 29 int r2=find(y); 30 if (r1!=r2){ 31 father[r1]=r2; 32 deep[r1]=cnt[r2]; 33 cnt[r2]+=cnt[r1]; 34 } 35 } 36 37 int ask(int x,int y){ 38 int r1=find(x); 39 int r2=find(y); 40 if (r1!=r2) 41 return -1; 42 return max(0,abs(deep[x]-deep[y])-1); 43 } 44 45 int main(){ 46 int T,x,y; 47 scanf("%d",&T); 48 pre(); 49 for (int i=1;i<=T;i++){ 50 scanf("%s",c); 51 scanf("%d %d",&x,&y); 52 if (c[0]=='M') merge(x,y); 53 if (c[0]=='C') printf("%d\n",ask(x,y)); 54 } 55 return 0; 56 }