UVA11987:Almost Union-Find
题意:给m,n分别表示元素个数和操作次数
操作分成3种:
- 1 p q 将p所在的集合和q所在的集合合并
- 2 p q 将p移至q所在的集合
- 输出p所在集合的元素个数和元素和
思路:
并查集,通过编号标记节点,对于2操作,当移除一个元素时,改变元素的标记,相当于使此元素自成一树,然后进行1操作
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
using namespace std;
#define N 200005
int id[N],sum[N],cnt[N],fa[N];
int n,m,ID;
void init()
{
for(int i=1;i<=n;i++)
{
id[i] = i;
sum[i]=i;
cnt[i]=1;
fa[i]=i;
}
ID=n;
}
int m_find(int x)
{
if(x!=fa[x])
{
return fa[x] = m_find(fa[x]);
}
return x;
}
void uni(int a,int b)
{
int tx = m_find(a);
int ty = m_find(b);
if(tx!=ty)
{
fa[tx] = ty;
sum[ty] += sum[tx];
cnt[ty] += cnt[tx];
}
}
void del(int x)
{
int tx = m_find(id[x]);
sum[tx]-=x;
cnt[tx]--;
ID++;
id[x] = ID;
fa[ID] = ID;
cnt[ID]=1;
sum[ID]=x;
}
int main()
{
while(cin>>n>>m)
{
init();
while(m--)
{
int a,b,c;
cin>>a;
if(a==1)
{
cin>>b>>c;
uni(id[b],id[c]);
}
else if(a==2)
{
cin>>b>>c;
int tx = m_find(id[b]);
int ty = m_find(id[c]);
if(tx!=ty)
{
del(b);
uni(id[b],id[c]);
}
}
else
{
cin>>b;
int fx = m_find(id[b]);
cout<<cnt[fx]<<" "<<sum[fx]<<endl;
}
}
}
return 0;
}