UVa 11987 Almost Union-Find (虚拟点)【并查集】
<题目链接>
题目大意:
刚开始,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 (虚拟点)【并查集】的更多相关文章
- UVA 1664 Conquer a New Region (并查集+贪心)
并查集的一道比较考想法的题 题意:给你n个点,接着给你n-1条边形成一颗生成树,每条边都有一个权值.求的是以一个点作为特殊点,并求出从此点出发到其他每个点的条件边权的总和最大,条件边权就是:起点到终点 ...
- UVA - 10129 Play on Words(欧拉回路+并查集)
2.解题思路:本题利用欧拉回路存在条件解决.可以将所有的单词看做边,26个字母看做端点,那么本题其实就是问是否存在一条路径,可以到达所有出现过的字符端点.由于本题还要求了两个单词拼在一起的条件是前一个 ...
- UVA - 208 Firetruck(消防车)(并查集+回溯)
题意:输入着火点n,求结点1到结点n的所有路径,按字典序输出,要求结点不能重复经过. 分析:用并查集事先判断结点1是否可以到达结点k,否则会超时.dfs即可. #pragma comment(link ...
- UVA - 10129 Play on Words (欧拉回路+并查集)
思路: 分别存下每个字符串的首尾字符,以字符为结点,单词看作一条变,就变成了求欧拉回路了,先判断下图是否连通,然后根据欧拉回路的结论:最多只能有两个点的入读不等于初读,而且必须是一个点的出度恰好比入度 ...
- UVa 1395 苗条的生成树(Kruskal+并查集)
https://vjudge.net/problem/UVA-1395 题意: 给出一个n结点的图,求苗条度(最大边减最小边的值)尽量小的生成树. 思路: 主要还是克鲁斯卡尔算法,先仍是按权值排序,对 ...
- UVa 1664 Conquer a New Region(并查集)
https://vjudge.net/problem/UVA-1664 题意: n个城市形成一棵树,每条边有权值C(i,j).任意两个点的容量S(i,j)定义为i与j唯一通路上容量的最小值.找一个点, ...
- UVA - 11987 Almost Union-Find[并查集 删除]
UVA - 11987 Almost Union-Find I hope you know the beautiful Union-Find structure. In this problem, y ...
- UVa 11987 Almost Union-Find(支持删除操作的并查集)
传送门 Description I hope you know the beautiful Union-Find structure. In this problem, you’re to imple ...
- UVA 11987 - Almost Union-Find(并查集)
UVA 11987 - Almost Union-Find 题目链接 题意:给定一些集合,操作1是合并集合,操作2是把集合中一个元素移动到还有一个集合,操作3输出集合的个数和总和 思路:并查集,关键在 ...
- UVA 11987 Almost Union-Find (并查集+删边)
开始给你n个集合,m种操作,初始集合:{1}, {2}, {3}, … , {n} 操作有三种: 1 xx1 yy1 : 合并xx1与yy1两个集合 2 xx1 yy1 :将xx1元素分离出来合到yy ...
随机推荐
- 神经网络之 Batch Normalization
知乎 csdn Batch Normalization 学习笔记 原文地址:http://blog.csdn.net/hjimce/article/details/50866313 作者:hjimce ...
- Confluence 6 配置 简易信息聚合(RSS)
一个 Confluence 的管理员可以配置下面的 RSS 特性: Confluence 针对 RSS 聚合返回的最大项目数量. Confluence 针对 RSS 聚合允许的最大时间周期. 上面两个 ...
- ionic3 title 不居中问题
<ion-navbar> <ion-title style="text-align: center;">{{naveTitle}}<button io ...
- SpringBoot多环境区分
1.修改application.yml配置文件 spring: profiles: active: cppdy datasource: driver-class-name: com.mysql.jdb ...
- java多线程快速入门(十八)
Lock锁是JDK1.5之后推出的并发包里面的关键字(注意捕获异常,释放锁) Lock与synchronized的区别 Lock锁可以人为的释放锁(相当于汽车中的手动挡) synchronized当线 ...
- LeetCode(98): 验证二叉搜索树
Medium! 题目描述: 给定一个二叉树,判断其是否是一个有效的二叉搜索树. 一个二叉搜索树具有如下特征: 节点的左子树只包含小于当前节点的数. 节点的右子树只包含大于当前节点的数. 所有左子树和右 ...
- PyCharm新建.py文件时自动带出指定内容
如:给Pycharm加上头行 # coding:utf-8File—Setting—Editor--Code Style--File and Code Templates--Python Scrip ...
- Python属性(@property)
创建用于计算机的属性 在Python中,可以通过@property(装饰器)将一个方法转换为属性,从而实现用于计算的属性.将方法转换为属性后,可以直接通过方法名来访问方法,而不需要再添加一对小括号&q ...
- python 自动获取手机短信验证码
需要一个有权限的 APK 在手机实时存储短信到手机内存 /sdcard/smslog.txt 里(外部SD卡也可以知道能通过adb命令访问到): /***** ...... try {long tim ...
- C++ Primer 笔记——固有的不可移植的特性
1.为了支持底层编程,C++定义了一些固有的不可移植的特性,所谓不可移植特性是指因机器而异的特性. 2.一个位域中含有一定数量的二进制位,位域在内存中的布局是机器相关的.位域的类型必须是整型或枚举类型 ...