Almost Union-Find

这个题是一个合并并查集节点的一道题,首先要明白的是并起来的元素就相当于一颗二叉树一样,所以不可能随便的将一个二叉树的根节点删除掉,所以我们只能让它保持在她的原位但是废弃掉它所有的功能。所以,我们需要给每一个节点都给他一张能识别它的身份证,当我们要废除掉一个节点的时候,先废除掉她的功能,然后新开一个点来表示它,再把它和别的节点合并起来。

#include<bits/stdc++.h>
using namespace std;
int data[1000100],sum[1000010],cnt[1000010],id[1000010],n;
void init()
{
    int i;
    for(i=1;i<=n;i++)
    {
        data[i]=i;
        sum[i]=i;
        cnt[i]=1;
        id[i]=i;
    }
}
int getf(int x)
{
    if(x==data[x])
    {
        return x;
    }
    else
    {
        return data[x]=getf(data[x]);
    }
}
int main()
{
    int m,i,j,k,a,b,num;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        init();
        num=n+1;
        while(m--)
        {
            scanf("%d",&k);
            if(k==1)
            {
                scanf("%d%d",&a,&b);
                int x,y;
                x=id[a];
                y=id[b];
                x=getf(x);
                y=getf(y);
                if(x!=y)
                {
                    data[y]=x;
                    sum[x]+=sum[y];
                    cnt[x]+=cnt[y];
                }
            }
            else  if(k==2)
            {
                scanf("%d%d",&a,&b);
                int x,y;
                x=id[a];
                y=id[b];
                x=getf(x);
                y=getf(y);
                if(x!=y)
                {
                    sum[x]-=a;
                    cnt[x]--;
                    id[a]=num++;
                    x=id[a];
                    data[x]=y;
                    cnt[y]+=1;
                    sum[y]+=a;
                }
            }
            else
            {
                int x,y;
                scanf("%d",&x);
                x=id[x];
                x=getf(x);
                printf("%d %d\n",cnt[x],sum[x]);
            }
        }
    }
    return  0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值