I hope you know the beautiful Union-Find structure. In this problem, you're to implement something similar, but not identical.
The data structure you need to write is also a collection of disjoint sets, supporting 3 operations:
1 p q
Union the sets containing p and q. If p and q are already in the same set, ignore this command.
2 p q
Move p to the set containing q. If p and q are already in the same set, ignore this command
3 p
Return the number of elements and the sum of elements in the set containing p.
Initially, the collection contains n sets: {1}, {2}, {3}, ..., {n}.
There are several test cases. Each test case begins with a line containing two integers n and m (1<=n,m<=100,000), the number of integers, and the number of commands. Each of the next m lines contains a command. For every operation, 1<=p,q<=n. The input is terminated by end-of-file (EOF). The size of input file does not exceed 5MB.
For each type-3 command, output 2 integers: the number of elements and the sum of elements.
5 7 1 1 2 2 3 4 1 3 5 3 4 2 4 1 3 4 3 3
3 12 3 7 2 8
1是合并p和q的集合,2是把p这个点移动到集合q所在的集合中,3是询问p所在的集合元素个数和元素和。
1,3简单,主要是2。不能直接改变pa[p],把p接到q的集合中,这样的话若p有子结点,那些子结点就找不到原来的根结点了。为了能让p的子结点找到根结点,pa[p]不能改变。那么可以新建一个结点代表p,给p编号一个新的id,那么p原来的编号的作用就只有让他原来的子结点找到根结点了,以后要修改p的话都使用新的id。把p接到q集合中相当于把p从本来的集合中删掉,建立一个新结点id[p],在把这个新结点的集合和q的集合合并。
#include<cstdio> #include<algorithm> #include<iostream> #include<sstream> #include<cstring> #include<cmath> #include<queue> #include<map> #include<set> #include<stack> #define INF 0x3f3f3f3f #define MAXN 200010 #define MAXM 510 #define eps 1e-9 #define pi 4*atan(1.0) #define pii pair<int,int> using namespace std;; int N,M,pa[MAXN],sum[MAXN],num[MAXN],id[MAXN]; int find(int x){ return x==pa[x]?x:pa[x]=find(pa[x]); } void Union(int p,int q){ int x=find(p),y=find(q); if(x!=y){ sum[y]+=sum[x]; num[y]+=num[x]; pa[x]=y; } } void move(int p){ int x=find(id[p]); sum[x]-=p; num[x]--; id[p]=++N; sum[id[p]]=p; num[id[p]]=1; pa[id[p]]=id[p]; } int main(){ freopen("in.txt","r",stdin); while(scanf("%d%d",&N,&M)!=EOF){ for(int i=1;i<=N;i++){ id[i]=i; pa[i]=i; sum[i]=i; num[i]=1; } while(M--){ int type,p,q; scanf("%d",&type); if(type==1){ scanf("%d%d",&p,&q); Union(id[p],id[q]); } if(type==2){ scanf("%d%d",&p,&q); if(find(id[p])!=find(id[q])){ move(p); Union(id[p],id[q]); } } if(type==3){ scanf("%d",&p); int x=find(id[p]); printf("%d %d\n",num[x],sum[x]); } } } return 0; }