zoukankan      html  css  js  c++  java
  • UVA

    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 Union the sets containing p and q. If p and q are already in the same set, ignore this command. 2 p q Move p to the set containing q. If p and q are already in the same set, ignore this command. 3 p Return the number of elements and the sum of elements in the set containing p.
    Initially, the collection contains n sets: {1}, {2}, {3}, ..., {n}.
    Input
    There are several test cases. Each test case begins with a line containing two integers n and m (1 ≤ n,m ≤ 100,000), the number of integers, and the number of commands. Each of the next m lines contains a command. For every operation, 1 ≤ p,q ≤ n. The input is terminated by end-of-file (EOF).
    Output
    For each type-3 command, output 2 integers: the number of elements and the sum of elements.
    Explanation Initially: {1}, {2}, {3}, {4}, {5} Collection after operation 1 1 2: {1,2}, {3}, {4}, {5} Collection after operation 2 3 4: {1,2}, {3,4}, {5} (we omit the empty set that is produced when taking out 3 from {3}) Collection after operation 1 3 5: {1,2}, {3,4,5} Collection after operation 2 4 1: {1,2,4}, {3,5}
    Sample Input
    5 7 1 1 2 2 3 4 1 3 5 3 4 2 4 1 3 4 3 3
    Sample Output
    3 12 3 7 2 8

    题目意思:

    初始时,一共有n个元素的组合。

    给出三个操作:(k p q)

    k==1 p q:合并p, q所在的集合

    k==2 p q:把p移动到q所在的集合

    k==3 p:输出p所在的集合的元素的个数和元素之和

    分析:

    虚结点思想
    并查集中并没有删除的操作。
    所以就需要将删除的这个点的影响降到0,
    也就是给删除的点申请一个新的id,
    以后都是用这个新的id来表示这个点,
    这样原来的那个集合里的点p就没意义,自然影响就为0.
     
    #include <iostream>
    #include<algorithm>
    #include <cstdio>
    #include<cstring>
    #include<math.h>
    #include<memory>
    using namespace std;
    typedef long long LL;
    #define max_v 200005
    int pa[max_v];
    int sum[max_v];//sum[x] x(根结点)所在元素集合所有元素的和
    int id[max_v];//id[x]=y 表示x结点现在的编号为y
    int cnt[max_v];//cnt[x] x(根结点)所在集合元素的个数
    
    int n,m,tot;
    
    void make_set(int x)
    {
        pa[x]=sum[x]=id[x]=x;
        cnt[x]=1;
    }
    int find_set(int x)
    {
        if(x!=pa[x])
            pa[x]=find_set(pa[x]);
        return pa[x];
    }
    void union_set(int x,int y)//x合并到y
    {
        x=find_set(x);
        y=find_set(y);
        if(x==y)
            return ;
    
        pa[x]=y;
        sum[y]+=sum[x];
        cnt[y]+=cnt[x];
    
    }
    void del(int x)
    {
        int fx=find_set(id[x]);
        sum[fx]-=x;
        cnt[fx]--;
    
        tot++;
        id[x]=tot;
        pa[tot]=tot;
        sum[tot]=x;
        cnt[tot]=1;
    }
    int main()
    {
        int n,m,k;
        int x,y;
        while(~scanf("%d %d",&n,&m))
        {
            tot=n;
            for(int i=0;i<=n;i++)
                make_set(i);
            for(int i=0;i<m;i++)
            {
                scanf("%d",&k);
                if(k==1)//x合并到y
                {
                    scanf("%d %d",&x,&y);
                    union_set(id[x],id[y]);
                }else if(k==2)//x从原有集合拿出放入到y
                {
                    scanf("%d %d",&x,&y);
                    int fx=find_set(id[x]);
                    int fy=find_set(id[y]);
    
                    if(fx!=fy)
                    {
                        del(x);
                        union_set(id[x],id[y]);
                    }
                }else//输出x所在集合元素个数和所有元素和
                {
                    scanf("%d",&x);
                    int fx=find_set(id[x]);
                    printf("%d %d
    ",cnt[fx],sum[fx]);
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    jq 字符串去除空格
    wpf 加载资源文件
    wpf 寻找TreeView的子元素,并对其进行操作
    IIS发布MVC ASP.NET网站
    wpf Binding 小记录
    asp.net mvc表单异步提交
    把路径设置为全局变量
    MVC将服务器端的物理路径转换为服务器路径
    silverlight控件阴影效果示例
    NLP的12条前提假设
  • 原文地址:https://www.cnblogs.com/yinbiao/p/9432749.html
Copyright © 2011-2022 走看看