poj1988 //并查集

  #include <iostream>
  #include <stdio.h>
  #define MAXN 30001
using namespace std;
  
  int pre[MAXN], son[MAXN], vis[MAXN];
  
  int find(int x){
      if(pre[x]==x){
         return x;
     }
     int temp=pre[x];  //***递归思想,temp为存储x改变根节点后的根节点的临时变量
     pre[x]=find(pre[x]);
     vis[x]+=vis[temp];  //***x到改变前根节点的距离即x到temp的距离加上temp到根节点的距离
     return pre[x];
 }
 
 void jion(int x, int y){
     int px=find(x);
     int py=find(y);
     if(px!=py){
         pre[py]=px;
         vis[py]=son[px];  //***将x所在列放到y所在列上面后,find(y)到新合并后的根节点的距离即为合并前find(x)的子树的大小
         son[px]+=son[py];  //***合并后find(x)的子树大小即为合并前find(x)与find(y)的子树大小的和
     }
 }
 
 int main(void){
     int p;
     scanf("%d", &p);
     for(int i=1; i<=MAXN; i++){
         pre[i]=i;
         son[i]=1;
     }
     for(int i=1; i<=p; i++){
         char s[2];
         int x, y;
        scanf("%s", s);
         if(s[0]=='M'){
             scanf("%d%d", &x, &y);
             jion(x, y);
         }else{
             scanf("%d", &x);
             printf("%d\n", son[find(x)]-vis[x]-1);//***注意这里并不是输出son(x),因为我们并没有求出每个节点的子树的大小
         }
     }
     return 0;
 }

猜你喜欢

转载自blog.csdn.net/dukig/article/details/79748043