F - Almost Union-Find (UVA - 11987 )

- 题目大意

初始有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;
}

  

原文地址:https://www.cnblogs.com/alpacadh/p/8449443.html

时间: 2024-10-31 20:02:56

F - Almost Union-Find (UVA - 11987 )的相关文章

UVA - 11987 Almost Union-Find[并查集 删除]

UVA - 11987 Almost Union-Find I hope you know the beautiful Union-Find structure. In this problem, you’re to implement something similar, but not identical. The data structure you need to write is also a collection of disjoint sets, supporting 3 oper

UVA - 11987 - Almost Union-Find (又是并查集~)

UVA - 11987 Almost Union-Find Time Limit: 1000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description Problem A Almost Union-Find I hope you know the beautiful Union-Find structure. In this problem, you're to implement som

uva 11987 Almost Union-Find (并查集)

题目大意: 三个操作. 1. 合并两个集合 2.把第一个元素放到第二个集合里 3.输出集合的数量和和.. 思路分析: 要用p记录这个元素所在集合编号,然后用编号建立并查集. #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> using namespace std; typedef long long LL; int set[111111]; int cn

UVA 11987 - Almost Union-Find(并查集)

UVA 11987 - Almost Union-Find 题目链接 题意:给定一些集合,操作1是合并集合,操作2是把集合中一个元素移动到另一个集合,操作3输出集合的个数和总和 思路:并查集,关键在于操作2,对于并查集,要去除掉一个结点,如果该结点不是根那就好办了,那么就多开n个结点,每个结点初始父亲都是它的i + n,这样在移动的时候,就不用担心他是根结点了剩下就是普通的带权并查集了 代码: #include <cstdio> #include <cstring> const i

并查集间单个节点的转移(UVa 11987 Almost Union-Find)

从来没有这么艰难地完成一道算法题过!经过8次失败之后总算提交成功了!所以决定写一篇博文,对并查集的相关内容做一些总结. 普通并查集的操作无非是两种,find_set(x)即找到节点x所在的集合的代表节点,或者是union_set(x,y),即将x和y所在的两个集合合并起来.如下图所示,有左右两个并集 通常,我们会选用并查集中父节点为自己的元素作为这个并查集的代表,例如图中的节点a和节点e.那么,我们如何通过集合中的一个节点找到该节点所在集合的代表节点呢?其实很简单,例如上图中的d节点,它首先通过

UVa 11987 Almost Union-Find(支持删除操作的并查集)

传送门 Description I hope you know the beautiful Union-Find structure. In this problem, you’re to implement something similar, but not identical. The data structure you need to write is also a collection of disjoint sets, supporting 3 operations: 1 p q

UVA 11987 并查集删点

并查集删点就是弄个id记录当前点的id,删除的时候将id设为新的id,忽略原来的id,当然还要注意去改变原来集合需要维护的性质比如元素个数等等. #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) m

UVA - 11987 Almost Union-Find(带删除的并查集)

Almost Union-Find Time Limit: 1000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description Problem A Almost Union-Find I hope you know the beautiful Union-Find structure. In this problem, you're to implement something simil

UVa 11987 并查集 Almost Union-Find

原文戳这 与以往的并查集不同,这次需要一个删除操作.如果是叶子节点还好,直接修改父亲指针就好. 但是如果要是移动根节点,指向它的所有子节点也会跟着变化. 所以要增加一个永远不会被修改的虚拟根节点,这样就可以把一个点从集合中删除而不影响其它的点了. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std