LA3027简单带权并查集

题意:
      有n个点,一开始大家都是独立的点,然后给出一些关系,a,b表示a是b的父亲节点,距离是abs(a-b)%1000,然后有一些询问,每次询问一个节点a到父亲节点的距离是多少?


思路:
     可以直接简单带权并查集就能搞定,核心代码是这样,设s_x[i]表示i到自己父亲节点的距离,然后
//处理并查集的时候
int finds(int x)
{
  if(x == mer[x]) return x;
  int k = mer[x];
  mer[x] = finds(mer[x]);
  mer[x] += mer[k];
  return mer[x];
}


//建立关系的时候


mer[a] = b;
s_x[a] = abs(a - b) % 1000


//询问的时候
x = finds(a);//这一部别忘记了,因为并查集用了路径压缩,查询一次之后才能更新到他到根的距离,不然后可能只是他到他上一个节点的距离,查询后经过路径压缩会把他上一个节点变成他的根节点。
printf(s_x[a]);








#include<stdio.h>
#include<string.h>


#define N 22000


int mer[N] ,s_x[N];


int abss(int x)
{
   return x > 0 ? x : -x;
}


int finds(int x)
{
    if(x == mer[x]) return x;
    int k = mer[x];
    mer[x] = finds(mer[x]);
    s_x[x] =(s_x[x] + s_x[k]);
    return mer[x];
}


int main ()
{
    int t ,n ,a ,b;
    char str[5];
    scanf("%d" ,&t);
    while(t--)
    {
       scanf("%d" ,&n);
       for(int i = 0 ;i <= n ;i ++)
       mer[i] = i ,s_x[i] = 0;
       while(~scanf("%s" ,str) && str[0] != 'O')
       {
          if(str[0] == 'I')
          {
             scanf("%d %d" ,&a ,&b);
             mer[a] = b;
             s_x[a] = abss(a - b) % 1000;
          }
          else
          {
               scanf("%d" ,&a);
               finds(a);
               printf("%d " ,s_x[a]);
          }
       }
    }
    return 0;
}



原文地址:https://www.cnblogs.com/csnd/p/12062562.html