<题目链接>

题目大意:

刚开始,1到n个集合中分别对应着1~n这些元素,然后对这些集合进行三种操作:

输入 1 a b 把a,b所在的集合合并 
输入 2 a b 把b从b所在的旧集合移到a的集合中 
输入 3 a 输出a所在集合的元素个数和这个集合的元素和。

解题分析:

1,3操作容易实现,但是2操作,如果仅仅只是简单的将father[a]=find(b) 的话,就错了,因为a可能恰好为那个集合的根节点,那么这种做法会将a的所有子节点也全部移动到b集合。因此,我们并不对a进行真正物理位置上的移动,而是假设a移动到了b集合,在b集合加入a的一个虚拟点,模拟a移动到b集合,实际上a还在原来的集合待着,但是这时,原来的a已经不会对本题产生任何影响,因为此时,两个集合所维护的两个值正常更新,并且我们认为a已经移动到了b , a的 id 也从原来的位置变到了新分配到的位置。通过这个虚拟点的建立,我们就能够模拟a移动到b集合的操作。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

;
int n,m,pos;
int father[M],sum[M],tot[M],id[M];

void init(){
    ;i<M;i++){
        father[i]=i;
        sum[i]=i;    //该集合所有元素总和
        tot[i]=;    //该集合元素个数
        id[i]=i;     //为i的实际所在位置(假设真的进行物理位置上的移动)
    }
    pos=n;
}
int find(int x){
    if(father[x]==x)return x;
    father[x]=find(father[x]);
    return father[x];
}
void Union(int x,int y){
    int f1=find(x),f2=find(y);
    if(f1!=f2){
        father[f1]=f2;
        tot[f2]+=tot[f1];   //更新这两个值
        sum[f2]+=sum[f1];
    }
}
//将a移动到b的集合
void Move(int a,int b){   //只进行数值上的虚拟移动,而不进行点的位置移动,即,移完后,a还在原来的集合,但是对结果不产生影响,同时我们假装a已经移动到了id[i]这个点
    int f1=find(id[a]),f2=find(b);   //因为b传过来的是真实的位置
    if(f1!=f2){
        tot[f2]++,tot[f1]--;     //模拟移动,更新这两个集合根节点维护的值
        sum[f2]+=a,sum[f1]-=a;
        id[a]=++pos;     //给这个虚拟点分配一个位置
        father[pos]=f2;  //这个虚拟点的father设为f2
    }
}
int main(){
    while(scanf("%d%d",&n,&m)!=EOF){
        init();
        while(m--){
            int op,a,b;
            scanf("%d%d",&op,&a);
            ){
                scanf("%d",&b);
                Union(id[a],id[b]);
            }
            ){
                scanf("%d",&b);
                Move(a,id[b]);
            }
            else{
                int root=find(id[a]);
                printf("%d %d\n",tot[root],sum[root]);
            }
        }
    }
    ;
}

2018-10-04

UVa 11987 Almost Union-Find (虚拟点)【并查集】的更多相关文章

  1. UVA 1664 Conquer a New Region (并查集+贪心)

    并查集的一道比较考想法的题 题意:给你n个点,接着给你n-1条边形成一颗生成树,每条边都有一个权值.求的是以一个点作为特殊点,并求出从此点出发到其他每个点的条件边权的总和最大,条件边权就是:起点到终点 ...

  2. UVA - 10129 Play on Words(欧拉回路+并查集)

    2.解题思路:本题利用欧拉回路存在条件解决.可以将所有的单词看做边,26个字母看做端点,那么本题其实就是问是否存在一条路径,可以到达所有出现过的字符端点.由于本题还要求了两个单词拼在一起的条件是前一个 ...

  3. UVA - 208 Firetruck(消防车)(并查集+回溯)

    题意:输入着火点n,求结点1到结点n的所有路径,按字典序输出,要求结点不能重复经过. 分析:用并查集事先判断结点1是否可以到达结点k,否则会超时.dfs即可. #pragma comment(link ...

  4. UVA - 10129 Play on Words (欧拉回路+并查集)

    思路: 分别存下每个字符串的首尾字符,以字符为结点,单词看作一条变,就变成了求欧拉回路了,先判断下图是否连通,然后根据欧拉回路的结论:最多只能有两个点的入读不等于初读,而且必须是一个点的出度恰好比入度 ...

  5. UVa 1395 苗条的生成树(Kruskal+并查集)

    https://vjudge.net/problem/UVA-1395 题意: 给出一个n结点的图,求苗条度(最大边减最小边的值)尽量小的生成树. 思路: 主要还是克鲁斯卡尔算法,先仍是按权值排序,对 ...

  6. UVa 1664 Conquer a New Region(并查集)

    https://vjudge.net/problem/UVA-1664 题意: n个城市形成一棵树,每条边有权值C(i,j).任意两个点的容量S(i,j)定义为i与j唯一通路上容量的最小值.找一个点, ...

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

    UVA - 11987 Almost Union-Find I hope you know the beautiful Union-Find structure. In this problem, y ...

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

    传送门 Description I hope you know the beautiful Union-Find structure. In this problem, you’re to imple ...

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

    UVA 11987 - Almost Union-Find 题目链接 题意:给定一些集合,操作1是合并集合,操作2是把集合中一个元素移动到还有一个集合,操作3输出集合的个数和总和 思路:并查集,关键在 ...

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

    开始给你n个集合,m种操作,初始集合:{1}, {2}, {3}, … , {n} 操作有三种: 1 xx1 yy1 : 合并xx1与yy1两个集合 2 xx1 yy1 :将xx1元素分离出来合到yy ...

随机推荐

  1. Oracle数据库内存使用情况分析查看

    SGA.PGA使用情况 select name,total,round(total-free,2) used, round(free,2) free,round((total-free)/total* ...

  2. Confluence 6 反向跟踪

    当反向跟踪(Trackback )被启用后,在任何你链接到可用启用自动发现功能的外部页面中,Confluence 将会自动发送一个方向跟踪 ping,这个 ping 能通知链接的页面有了内容改变. C ...

  3. bat如何提取文本指定行的内容

    背景:使用CTS框架运行完测试后,会在logs中生成devices_log和host_log,在results中生成相应的结果(报告).根据报告信息我们可以得知失败的用例,但是却不能知道为什么用例会失 ...

  4. Mycat实现mysql主从复制(读写分离)

    数据库性能瓶颈主要原因: 随着用户数的增多,带来的是数据库连接的大幅度增长 随着业务体量的增长,表数据量(空间存储的问题)的大幅增长,其中涉及到索引的优化,mysql默认的索引是硬盘级别的,BTREE ...

  5. LabView(控件部分)

    1.虚拟仪器的概述: 虚拟仪器是基于计算机的的仪器,计算机和仪器的密切结合是目前仪器的一个发展方向,大概有两种结合方式,一种是将计算机装入仪器中,实例就是只能化的仪器,流行的嵌入式系统的仪器,另一种就 ...

  6. 课外知识----ini

    ini    初始化英文单词的缩写,用来初始化参数 ini文件配置 [小节] 键=值 [小节] 键=值

  7. hdu3586 树形dp+二分答案

    /* dp[i]表示孤立i结点的费用,二分功率上限w,即dp[i]在选择时不可以选择功率大于w的边 */ #include<bits/stdc++.h> using namespace s ...

  8. 解决:sudo: pip: command not found

    1-问题:Ubuntu下执行sudo pip install package-name 出现 sudo: pip: command not found 的问题. 2-原因:编译sudo的时候加入了–w ...

  9. C和Java判断一个数字是否为素数

    C: /* 素数: 素数又称质数.所谓素数是指除了 1 和它本身以外,不能被任何整数整除的数,例如17就是素数,因为它不能被 2~16 的任一整数整除. */ # include <stdio. ...

  10. SQL Server索引的执行计划

    如何知道索引有问题,最直接的方法就是查看执行计划.通过执行计划,可以回答表上的索引是否被使用的问题. (1)包含索引:避免书签查找 常见的索引方面的性能问题就是书签查找,书签查找分为RID查找和键值查 ...