zoukankan      html  css  js  c++  java
  • UVA11987Almost Union-Find(并查集删除节点)

    题目链接

    题意:n个数(即1-n)和m个操作:

    1表示把x和y合并,2表示把x移到y集合里面,3表示统计x集合的元素个数

    1,3好说,关键是2操作,可以先把2删除掉,删除的操作可以找一个其他的数字来取代x,这样就有新生出来一个集合,移到y集合就合并

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    const int N = 100000;
    typedef long long LL;
    int father[N + N + 10];
    int sum[N + N + 10],cnt[N + N + 10];  // sum求集合里面所有元素和,cnt表示个数
    int value[N + N + 10]; //表示第i个数值 
    int n,m,k;
    void init()
    {
        k = n + 1;
        for(int i = 0; i <= n; i++)
        {
            father[i] = i;
            sum[i] = i;
            cnt[i] = 1;
            value[i] = i;
        }
    }
    int Find(int x)
    {
        if(x == father[x])
            return x;
        return father[x] = Find(father[x]);
    }
    void Union(int x, int y)
    {
        int fx = Find(x);
        int fy = Find(y);
        if(fx != fy)
        {
            father[fx] = fy;
            sum[fy] += sum[fx];
            cnt[fy] += cnt[fx];
        }
    }
    void Remove(int x)
    {
        /*
        int fx = Find(value[x]);
        cnt[fx]--;
        sum[fx] -= x;
        value[x] = k;
        int fy = Find(value[y]);
        father[k] = fy;
        cnt[fy]++;
        sum[fy] += x;
        k++;
        */
        int fx = Find(value[x]);
        cnt[fx]--;  // 删除x时从父节点集合中减一
        sum[fx] -= x;  // sum中减去x
        value[x] = k;  // 用 k 来代替 x ,生成了一个单独的集合,父节点是k
        cnt[k] = 1;    
        sum[k] = x;
        father[k] = k;
        k++;
    }
    int main()
    {
        while(scanf("%d%d", &n, &m) != EOF)
        {
            k = n + 1;
            for(int i = 0; i <= n; i++)
            {
                father[i] = i;
                sum[i] = i;
                cnt[i] = 1;
                value[i] = i;
            }
            int order,p,q;
            while(m--)
            {
                scanf("%d", &order);
                if(order == 1)
                {
                    scanf("%d%d", &p, &q);
                    Union(value[p], value[q]);
                }
                else if(order == 2)
                {
                    scanf("%d%d", &p, &q);
                    int fx = Find(value[p]);
                    int fy = Find(value[q]);
                    if(fx != fy)   // 如果p和q本来就在一个集合,就不用操作了。但是少了这个就wa了,不明白为什么操作不行
                    {
                        Remove(p);
                        Union(value[p], value[q]);
                    }
                }
                else if(order == 3)
                {
                    scanf("%d", &p);
                    int fx = Find(value[p]);
                    printf("%d %d
    ", cnt[fx], sum[fx]);
                }
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    解决远程连接mysql很慢的方法(网络正常)
    分布式系统中可用性及容错性的区别
    设计模式个人思考
    记第一次多用户在Git提交代码
    Git远程分支的回退
    Linux模拟控制网络时延
    ubuntu 软件
    编译cubieboard android 源码过程详解之(六):pack
    编译cubieboard android 源码过程详解之(五):make
    编译cubieboard android 源码过程详解之(四):extract-bsp
  • 原文地址:https://www.cnblogs.com/zhaopAC/p/5249060.html
Copyright © 2011-2022 走看看