1. 程式人生 > >F - Almost Union-Find (UVA - 11987 )

F - Almost Union-Find (UVA - 11987 )

include .... mos space 初始 gpo ret num std

- 題目大意

初始有N個集合,分別為 1 ,2 ,3 .....n。一共有三種操件:
1、 p q 合並元素p和q的集合
2 、p q 把p元素移到q集合中
3 、p 輸出p元素集合的個數及全部元素的和。

- 解題思路

並查集操作。1、3步比較容易實現,只要建立一個sum[],cnt[],記錄每個結點相應值,和並時把值更新到根結點,輸出時只要找到根結點輸出其值即可。第二步可以利用並查集的刪除功能去構造即可。

- 代碼

#include<cstdio>
using namespace std;
const int MAX=1e5+50;
int fa[MAX];
int num[MAX],id[MAX];
long long sum[MAX];
int find(int x)
{
    if(x==fa[x])
        return x;
    else
        return fa[x]=find(fa[x]);
}

void init(int n)
{
    for(int i=0;i<=n;i++)
       {
        sum[i]=fa[i]=id[i]=i;
        num[i]=1;
       }
}

void Union(int x,int y)
{
    int fx=find(x),fy=find(y);
    if(fx!=fy)
   {
    fa[fx]=fy;
    sum[fy]+=sum[fx];
    num[fy]+=num[fx];
   }
}
int main()
{
    int n,m,x,y,tmp;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        tmp=n;
        init(n);
        int choose;
        while(m--)
        {
        scanf("%d",&choose);
        if(choose==1)
        {
            scanf("%d%d",&x,&y);
            Union(id[x],id[y]);
        }
        else if(choose==2)
        {
            scanf("%d%d",&x,&y);
            int fx=find(id[x]),fy=find(id[y]);
            if(fx!=fy)
            {
                sum[fx]-=x;
                num[fx]--;
                tmp++;
                id[x]=tmp;
                fa[tmp]=tmp;
                num[tmp]=1;
                sum[tmp]=x;
                Union(id[x],id[y]);
            }
        }
        else
        {
            scanf("%d",&x);
            int fx=find(id[x]);
            printf("%d %d\n",num[fx],sum[fx]);
        }
      }
    }
    return 0;
}

  

F - Almost Union-Find (UVA - 11987 )