• UVA 11987 Almost Union-Find (并查集+删边)


      开始给你n个集合,m种操作,初始集合:{1}, {2}, {3}, … , {n} 
    操作有三种: 
    1 xx1 yy1 : 合并xx1与yy1两个集合 
    2 xx1 yy1 :将xx1元素分离出来合到yy1上 
    3 xx1 :查询xx1集合的元素个数,和元素所有值总和

      并查集,1就是合并两个集合,3要记录两个权值。因为只要祖先的权值,所以Find操作不需要更新权值。 
      接着就是分离元素了,在这儿我使用映射的方法:开始每个元素都映射自己,接着要删除元素时,我不直接删除元素(因为删除的话可能影响很大),我把此位置映射到不可能出现过得的新的一个值,这样我们处理一下原来的集合,再使用新的值维护一下现在的集合就好了,因为以后我们只是看映射的值,所以虽然没有直接删除值,但是原来的值我们不用。

    #include<set>
    #include<map>
    #include<queue>
    #include<stack>
    #include<cmath>
    #include<vector>
    #include<string>
    #include<cstdio>
    #include<cstring>
    #include<stdlib.h>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    #define eps 1E-8
    /*注意可能会有输出-0.000*/
    #define Sgn(x) (x<-eps? -1 :x<eps? 0:1)//x为两个浮点数差的比较,注意返回整型
    #define Cvs(x) (x > 0.0 ? x+eps : x-eps)//浮点数转化
    #define zero(x) (((x)>0?(x):-(x))<eps)//判断是否等于0
    #define mul(a,b) (a<<b)
    #define dir(a,b) (a>>b)
    typedef long long ll;
    typedef unsigned long long ull;
    const int Inf=1<<28;
    const double Pi=acos(-1.0);
    const int Mod=1e9+7;
    const int Max=200010;
    int fat[Max],num[Max];
    ll ran[Max];
    int mp[Max],tot;//下标映射数字 找新值的代替前面的
    void Init(int n)
    {
        for(int i=0;i<=n;i++)
        {
            fat[i]=i;
            ran[i]=(ll)i;
            num[i]=1;
            mp[i]=i;
        }
        tot=n+1;
        return;
    }
    int Find(int x)
    {
        if(x==fat[x])
            return fat[x];
        return fat[x]=Find(fat[x]);
    }
    void Union(int x,int y,int typ)
    {
        int prex=x;//注意保存原来的值
        x=mp[x],y=mp[y];//注意映射
        int x1=Find(x);
        int y1=Find(y);
        if(x1==y1)
        return;
        if(typ==1)
        {
        fat[x1]=y1;
        ran[y1]+=ran[x1];
        num[y1]+=num[x1];
        return;
        }
        mp[prex]=tot++;//删除原有,添加到新地方,注意mp
    
        fat[mp[prex]]=y1;
        num[mp[prex]]=1;
        ran[mp[prex]]=(ll)x;
    
        num[x1]--;
        ran[x1]-=(ll)prex;
    
        num[y1]++;
        ran[y1]+=(ll)prex;
        return;
    }
    int main()
    {
        int n,m;
        int typ,xx1,yy1;
        while(~scanf("%d %d",&n,&m))
        {
            Init(n);
            for(int i=0;i<m;i++)
            {
                scanf("%d",&typ);
                if(typ==1)
                {
                    scanf("%d %d",&xx1,&yy1);
                    Union(xx1,yy1,1);
                }
                else if(typ==2)
                {
                scanf("%d %d",&xx1,&yy1);
                Union(xx1,yy1,2);
                }
                else
                {
                    scanf("%d",&xx1);
                    yy1=Find(mp[xx1]);
                    printf("%d %lld
    ",num[yy1],ran[yy1]);
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    (C#基础) byte[] 之初始化, 赋值,转换。
    System.IO.IOException: The handle is invalid.
    .NET 自动内存管理(垃圾收集GC)
    Inconsistent accessibility
    有用的网址
    dw添加emmet
    行内标签,怎么取消两个标签中间的距离
    2016.6.2近日学习计划
    HTML5 input placeholder 颜色修改示例
    加入收藏和设为首页
  • 原文地址:https://www.cnblogs.com/zhuanzhuruyi/p/5863745.html
Copyright © 2020-2023  润新知