题目链接:
题解:
就是简单的并查集,只不过包括了转移一个元素,而不是整个集合。方法很简单:
法一:
将对每一个元素,将他们的祖先设置成一个不存在的结点,这样就可以自由的操作了,并对每个集合直接进行修改。
法二:
(某whx同学教我的)
无需删除被移除的元素,只要将它标记一下,再在将要被移到的那个集合里加上那个元素即可。
下面我给出法一的代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 400010
int f[N],size[N];
long long sum[N];
int n,m,opt;
int find(int x) { return x == f[x] ? x : f[x] = find(f[x]); }
int main()
{
int p,q;
while(scanf("%d%d",&n,&m) != EOF)
{
for(int i = 1;i <= n;i++) {f[i] = i+n;f[i+n] = i+n;size[i+n] = 1; sum[i+n] = i; }
while(m--)
{
scanf("%d",&opt);
if(opt == 1)
{
scanf("%d%d",&p,&q);
int fa = find(p),fb = find(q);
if(fa != fb)
{
f[fb] = fa;
size[fa] += size[fb];
sum[fa] += sum[fb];
}
}
if(opt == 2)
{
scanf("%d%d",&p,&q);
int fa = find(p),fb = find(q);
if(fa != fb)
{
f[p] = fb;
size[fb] ++; sum[fb] += p;
size[fa] --; sum[fa] -= p;
}
}
if(opt == 3)
{
scanf("%d",&p);
int fa = find(p);
printf("%d %lld\n",size[fa],sum[fa]);
}
}
}
return 0;
}