UVa 11987 Almost Union-Find(支持删除操作的并查集)
Description
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
思路
题意:
给出1-N的数,一开始每个数自形成一个集合,要求支持以下操作
- 将元素 p 所在集合与元素 q 所在集合合并
- 将元素 p 移到元素 q 所在集合
- 询问元素 p 所在集合有多少个元素,和为多少
题解:
第一和第三个操作都是很裸的并查集,关键在于操作2,很容易可以想到,元素 p 移到元素 q所在集合,可以先在元素 p 所在集合将其删除,然后把元素 p 与元素 q 所在集合合并。而这一步的关键在于删除操作,如果 p 是叶子节点,直接改变 p 的父亲指向就行,但是 p 即所在集合的根节点又当如何,将其删除的话其子节点需要重新建立关系,这个过程还是有一定复杂性的。我们可以采取另外的思路:二次哈希法(ReHash),对于每个结点都有一个哈希值,在进行查找之前需要将x转化成它的哈希值HASH[x],那么在进行删除的时候,只要将x的哈希值进行改变,变成一个从来没有出现过的值(可以采用一个计数器来实现这一步),然后对新的值建立集合,因为只有它一个元素,所以必定是一个新的集合。这样做可以保证每次删除操作的时间复杂度都是O(1)的,而且不会破坏原有树结构,唯一的一个缺点就是每删除一个结点其实是多申请了一块内存,如果删除操作无限制,那么内存会无限增长。
简单的说,就是建立虚拟节点,这样原来的节点还在树当中,并不会破坏其结构,开辟一个id[ ]数组表示元素 x 对应的值。
- #include<bits/stdc++.h>
- using namespace std;
- const int maxn = 100005;
- int cnt,fa[maxn],num[maxn],sum[maxn],id[maxn];
- void init(int N)
- {
- for (int i = 0;i <= N;i++)
- {
- fa[i] = id[i] = sum[i] = i;
- num[i] = 1;
- }
- cnt = N;
- }
- int find(int x)
- {
- int r = x;
- while (r != fa[r]) r = fa[r];
- int i = x,j;
- while (i != r)
- {
- j = fa[i];
- fa[i] = r;
- i = j;
- }
- return r;
- }
- void Union(int x,int y)
- {
- int fx = find(id[x]),fy = find(id[y]);
- fa[fx] = fy;
- num[fy] += num[fx];
- sum[fy] += sum[fx];
- }
- void Delete(int x)
- {
- int fx = find(id[x]);
- --num[fx];
- sum[fx] -= x;
- id[x] = ++cnt,fa[id[x]] = id[x],num[id[x]] = 1,sum[id[x]] = x;
- }
- int main()
- {
- int N,M;
- while (~scanf("%d%d",&N,&M))
- {
- int opt,x,y;
- init(N);
- while (M--)
- {
- scanf("%d",&opt);
- if (opt == 1)
- {
- scanf("%d%d",&x,&y);
- if (find(id[x]) != find(id[y])) Union(x,y);
- }
- else if (opt == 2)
- {
- scanf("%d%d",&x,&y);
- if (find(id[x]) != find(id[y])) Delete(x),Union(x,y);
- }
- else
- {
- scanf("%d",&x);
- printf("%d %d\n",num[find(id[x])],sum[find(id[x])]);
- }
- }
- }
- return 0;
- }
UVa 11987 Almost Union-Find(支持删除操作的并查集)的更多相关文章
- UVa 10129 Play On Words【欧拉道路 并查集 】
题意:给出n个单词,问这n个单词能否首尾接龙,即能否构成欧拉道路 按照紫书上的思路:用并查集来做,取每一个单词的第一个字母,和最后一个字母进行并查集的操作 但这道题目是欧拉道路(下面摘自http:// ...
- UVA - 11987 Almost Union-Find(带删除的并查集)
I hope you know the beautiful Union-Find structure. In this problem, you’re to implement something s ...
- 【uva 247】Calling Circles(图论--Floyd 传递闭包+并查集 连通分量)
题意:有N个人互相打了M次电话,请找出所有电话圈(Eg.a→b,b→c,c→d,d→a 就算一个电话圈)并输出.(N≤25,L≤25,注意输出格式) 解法:由于N比较小所有n^2或n^3的复杂度都没有 ...
- 洛谷UVA11987Almost Union-Find题解--并查集的删除
题目链接 https://www.luogu.org/problemnew/show/UVA11987 分析 分析下操作发现就是加了个删除操作的并查集,怎么做删除操作呢. 我们用一个\(id[]\)记 ...
- 并查集(删除) UVA 11987 Almost Union-Find
题目传送门 题意:训练指南P246 分析:主要是第二种操作难办,并查集如何支持删除操作?很巧妙的方法:将并查集树上p的影响消除,即在祖先上(sz--, sum -= p),然后为p换上马甲:id[p] ...
- hdu4496并查集的删边操作
题意: 给你一个图,问你删除一些边后还有几个连通快.. 思路: 典型的并查集删边操作,并查集的删边就是先把不删除的边并查集一边(本题没有不删除的边),然后逆序吧所有要删除的边以 ...
- POJ 1611 The Suspects 并查集 Union Find
本题也是个标准的并查集题解. 操作完并查集之后,就是要找和0节点在同一个集合的元素有多少. 注意这个操作,须要先找到0的父母节点.然后查找有多少个节点的额父母节点和0的父母节点同样. 这个时候须要对每 ...
- 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 并查集的删除
Almost Union-Find I hope you know the beautiful Union-Find structure. In this problem, you're to imp ...
随机推荐
- RMAN-06023: no backup or copy of datafile 1 found to restore
在ORACLE 10g数据库还原过程遭遇RMAN-06023: no backup or copy of datafile x found to restore,具体情况如下所示 .......... ...
- ORA-12520: TNS:listener could not find available handler for requested type of server
当你碰到ORA-12520错误时,如下所示: 英文错误提示: ORA-12520: TNS:listener could not find available handler for requeste ...
- 测试几个xml的问题
使用sql server的时候,免不了与xml的参数打交道,xml大多数时候都给我们的程序带来方便,但是也有些时候会有变量赋值不通过的时候.(当然罗,如果你本身xml都通不过 xml spy 之类软件 ...
- html iframe 元素之间的调用
html iframe 元素之间的调用一.简介 一般需要引入一个独立页面的时候,我们会使用iframe.在业务需要的时候,我们需要在父页面与iframe页面之间进行交互.交互的时候,我们就需要使 用到 ...
- python paramiko 进行文件上传处理
#!/usr/bin/env python # -*- coding:utf-8 -*- import paramiko import uuid class Ha(object): def __ini ...
- Android开机启动程序
android程序实现开机启动的原理,简单点说就是做一个广播接收器,接收到开机广播时就启动activity或service或执行其它操作.Android系统在启动的时候会发出一个开机广播,内容为ACT ...
- Linux服务器磁盘扩展和oracle表空间文件迁移操作记录
1.环境介绍 服务器硬件:Dell R710 服务器OS:红帽子Linux RHEL4.8 数据库:Oracle 10g 2.出现的问题 因为数据表每天有上百万的数据写入表,加上建立索引,导致表空 ...
- HDU 5183 Negative and Positive (NP) --Hashmap
题意:问有没有数对(i,j)(0<=i<=j<n),使得a[i]-a[i+1]+...+(-1)^(j-i)a[j]为K. 解法:两种方法,枚举起点或者枚举终点. 先保存前缀和:a1 ...
- Hibernate一对多关联
一对多双向关联关系:(Dept/Emp的案例) 既可以根据在查找部门时根据部门去找该部门下的所有员工,又能在检索员工时获取某个员工所属的部门. 步骤如下: 1.构建实体类(部门实体类加set员工集合) ...
- 洛谷P1330封锁阳光大学[二分图染色]
题目描述 曹是一只爱刷街的老曹,暑假期间,他每天都欢快地在阳光大学的校园里刷街.河蟹看到欢快的曹,感到不爽.河蟹决定封锁阳光大学,不让曹刷街. 阳光大学的校园是一张由N个点构成的无向图,N个点之间由M ...