Description
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}.
Input Description
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.
Output Description
For each type-3 command, output 2 integers: the number of elements and the sum of elements.
Sample Input
5 7 1 1 2 2 3 4 1 3 5 3 4 2 4 1 3 4 3 3
Sample Output
3 12 3 7 2 8
/*
这是一个需要删除的并查集。我尝试过用father和son。比较麻烦。而且最终超时了。。
看了题解,需要删除点的并查集,转换为带权并查集,直接将需要删除的点的权值置0;
操作1:将两个并查集合并,得同时合并num和sum.
操作2:比如删除x.idx[x]表示真正的x在哪里。先将此个x权值置0.再开个新的点。然后合并该点和q即可
*/
#include <iostream>
#include <cstdio>
using namespace std;
#define maxn 200018
int father[maxn],idx[maxn],num[maxn];//num来多少个,idx才存
long long int sum[maxn];
int n,m,cnt;
int find(int x)
{
if(x==father[x])return x;
return find(father[x]);
}
void init()
{
for(int i=1;i<=n;i++)
{
father[i]=idx[i]=sum[i]=i;
num[i]=1;
}
cnt=n;
}
void Union(int p,int q)
{
int pp=find(idx[p]),qq=find(idx[q]);
father[pp]=qq;
num[qq]+=num[pp];
sum[qq]+=sum[pp];
}
void Delete(int p)
{
int pp=idx[p];
sum[find(pp)]-=p;
num[find(pp)]--;
idx[p]=++cnt;sum[idx[p]]=p;num[idx[p]]=1;father[idx[p]]=idx[p];
}
int main()
{
while(scanf("%d%d",&n,&m)==2)
{
init();
int ope,p,q;
for(int i=1;i<=m;i++)
{
scanf("%d",&ope);
if(ope==1)
{
scanf("%d%d",&p,&q);
if(find(idx[p])==find(idx[q]))continue;
else Union(p,q);
}
else if(ope==2)
{
scanf("%d%d",&p,&q);
if(find(idx[p])!=find(idx[q]))
{
Delete(p);
Union(p,q);
}
}
else
{
int u;
scanf("%d",&u);
int fuck=find(idx[u]);
printf("%d %lld\n",num[fuck],sum[fuck]);//这里我用I64d既然WA。。。
}
}
}
return 0;
}