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