UVA - 11987 most union find

Posted by ultranet on Tue, 07 Jan 2020 04:33:36 +0100

Title Link

Main idea:

The following operations are given in the title: 1. Merge the two sets of p and q; 2. Move p into the set q; 3. Output the number of elements in the set of p and the sum of these elements.

Topic idea:

We know that the combination of two sets is to connect the root node of P to the root node of Q, and to move p to the set Q? Is it all right to just have the root node of f a [P] = q?

Of course not. In this way, we just move p to set q, but if P is not a leaf node, then the sons under P will also move to set q.

But we can think like this: can we separate the p-point and make it a set? Then it's equivalent to merging {p} with the set q. we don't need to worry about the problem that the following children will move;

Specific implementation: open an id [] array to save the information of p.

As for the elements of the output set and their sum, we can use num [] and sum [] to save them at any time. (add and subtract when moving)

Code:

#include<iostream>
#include<cstdio>
#define maxn 300005

using namespace std;
int fa[maxn];
int num[maxn],sum[maxn];
int id[maxn];//Why don't you bring your sons over
int n,m;

int finds(int x)
{
     return fa[x]==x?x:finds(fa[x]);
}
void remove1(int a,int b)//We're going to move it together
{
     a=finds(a);
     b=finds(b);
     if(a!=b)
     {
          fa[a]=b;
          num[b]+=num[a];
          num[a]=0;//The number of elements in the collection with aa as the root node is 0
          sum[b]+=sum[a];
          sum[a]=0;
     }

}
void remove2(int a,int b)//Mobile a only
{
     int aa=finds(id[a]);
     int bb=finds(b);
     if(aa!=bb)
     {
          id[a]=++n;
          fa[n]=bb;
          num[bb]++;
          num[aa]--;
          sum[bb]+=a;
          sum[aa]-=a;
     }
}
int main(void)
{

     int d,p,q;
     int pp,qq;
     while(~scanf("%d%d",&n,&m))
     {
          for(int i=1;i<=n;i++)
          {
               id[i]=i;
               num[i]=1;
               sum[i]=i;
               fa[i]=i;
          }
          for(int i=0;i<m;i++)
          {
               scanf("%d",&d);
               switch(d)
               {
                    case 1:
                         scanf("%d%d",&p,&q);
                         remove1(id[p],id[q]);
                         break;
                    case 2:
                         scanf("%d%d",&p,&q);
                         remove2(p,id[q]);//p is needed in the back
                         break;
                    case 3:
                         scanf("%d",&p);
                         pp=finds(id[p]);
                         printf("%d %d\n",num[pp],sum[pp]);//Represented by root node
                         break;
               }
          }
     }
     return 0;
}

Whirl

Topics: Mobile