<题目链接>

题目大意:

刚开始,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. ORA-00845 MEMORY_TARGET not supported on this system 的解决

    本文来源:宁静致远 的<ORA-00845 MEMORY_TARGET not supported on this system 的解决> oracle11g数据库在执行dbca或者调整s ...

  2. Confluence 6 配置服务器基础地址备注

    使用不同 URL.如果你配置了不同的基础 URL 地址或者你站点的访问者使用了不同的 URL 地址来访问你的 Confluence 地址,你有很大概率可能会受到错误信息. 修改上下文地址.如果你修改了 ...

  3. Confluence 6 理解你许可证的用户数

    基于你的许可证类型,在你 Confluence 可以被注册的用户也许有限制. 在许可证明细页面中,将会告诉当前使用了多少的许可证(你注册的用户数量). 包括仅仅在 Confluence 中可以使用gl ...

  4. Confluence 6 使用 CSS 样式化 Confluence 的介绍

    这个页面对 Confluence 通过修改 CSS 来改变外观和感觉的情况进行了说明. 层叠样式表(Cascading Style Sheets (CSS))是对 Web 页面进行样式化的工业化标准. ...

  5. axis 数据流

    产生数据流的代码 模板   重新修改了下 :]axis_data_cnt='d0; :]axis_data_frame_cnt='d0; :]delay_cnt='d0; initial begin ...

  6. day06 数字类型,字符串类型,列表类型

    一:整型int# ======================================基本使用======================================# 1.用途:记录年龄 ...

  7. C++ Primer 笔记——智能指针

    1.新的标准库提供了两种智能指针类型,shared_ptr允许多个指针指向同一个对象,unique_ptr则独占所指的对象.标准库还定义了一个名为weak_ptr的伴随类,它是一种弱引用,指向shar ...

  8. Just Oj 2017C语言程序设计竞赛高级组D: 字符串最大表示(next数组)

    D: 字符串最大表示 时间限制: 1 s      内存限制: 128 MB 题目描述 有如下定义,abcnabcn表示字符串abc重复n次,例如abc2abc2表示abcabc. 给定一个字符串,求 ...

  9. 将txt文本转换为excel格式

    将txt文本转换为excel格式,中间使用的列分割为 tab 键 一.使用xlwt模块 注:Excel 2003 一个工作表行数限制65536,列数限制256 需要模块:xlwt 模块安装:xlwt ...

  10. [转] 最详尽的 JS 原型与原型链终极详解

    四. __proto__ JS 在创建对象(不论是普通对象还是函数对象)的时候,都有一个叫做__proto__ 的内置属性,用于指向创建它的构造函数的原型对象. 对象 person1 有一个 __pr ...