UVA11987:Almost Union-Find

UVA11987:Almost Union-Find

题意:给m,n分别表示元素个数和操作次数
操作分成3种:

  1. 1 p q 将p所在的集合和q所在的集合合并
  2. 2 p q 将p移至q所在的集合
  3. 输出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;
}

猜你喜欢

转载自blog.csdn.net/carrie17/article/details/81988418