uva 11987 Almost Union-Find(并查集的删除操作)
2016-10-09 11:32
435 查看
题意:
初始时,一共有n个元素的组合1,2,3....n
给出三个操作
1 p q:合并p,q所在的集合
2 p q:把p移动到q所在的集合
3 p:输出p所在的集合的元素的个数
思路:1,3相当简单,赤裸裸的并查集就好了
麻烦的是2,并查集是单向的,只知道父亲不知道儿子
所有如果i是叶子节点无所谓
如果是父亲节点就会十分的蛋疼:
你是到另一个集合里面去了,你的儿子们呢?
把i这个点复制一下(编号为cnt++),当作叶子节点扔到新集合里去
原来的i仅仅有作为集合编号的作用,可以认为是个空点 ,只是为了不让原来的并查集出现错误,防止他的儿子们找不到根节点
重新找一个节点,记录这个节点自己的信息,也就是sum = 他自己, num = 1;
注意:合并或者查询等的时候一定要合并id[i],因为原来的i只是一个空节点了,为了保证并查集不出错而存在的,在del函数的时候,传参
要穿本身,因为一会要用到本身,新的节点的sum是他本身,并且对id数组更新的时候,下标也是他本身
代码:
初始时,一共有n个元素的组合1,2,3....n
给出三个操作
1 p q:合并p,q所在的集合
2 p q:把p移动到q所在的集合
3 p:输出p所在的集合的元素的个数
思路:1,3相当简单,赤裸裸的并查集就好了
麻烦的是2,并查集是单向的,只知道父亲不知道儿子
所有如果i是叶子节点无所谓
如果是父亲节点就会十分的蛋疼:
你是到另一个集合里面去了,你的儿子们呢?
把i这个点复制一下(编号为cnt++),当作叶子节点扔到新集合里去
原来的i仅仅有作为集合编号的作用,可以认为是个空点 ,只是为了不让原来的并查集出现错误,防止他的儿子们找不到根节点
重新找一个节点,记录这个节点自己的信息,也就是sum = 他自己, num = 1;
注意:合并或者查询等的时候一定要合并id[i],因为原来的i只是一个空节点了,为了保证并查集不出错而存在的,在del函数的时候,传参
要穿本身,因为一会要用到本身,新的节点的sum是他本身,并且对id数组更新的时候,下标也是他本身
代码:
#include<bits/stdc++.h> using namespace std; const int maxn = 3*1e5+5; int pre[maxn], id[maxn], num[maxn], sum[maxn], cnt; void init(int n) { cnt = n; for(int i = 1; i <= n; i++) pre[i] = i, num[i] = 1, sum[i] = i, id[i] = i; } int Find(int x) { int r = x; while(pre[r] != r) r = pre[r]; int i = x, j; while(pre[i] != r) { j = pre[i]; pre[i] = j; i = j; } return r; } void join(int x, int y) { int a = Find(x); int b = Find(y); if(a != b) { pre[b] = a; sum[a] += sum[b]; num[a] += num[b]; } } void del(int x) { int r = Find(id[x]); num[r]--; sum[r] -= x; cnt++; pre[cnt] = cnt; num[cnt] = 1; sum[cnt] = x; id[x] = cnt; } int main(void) { int n, m; while(cin >> n >> m) { init(n); while(m--) { int cmd, x, y; scanf("%d", &cmd); if(cmd == 1) { scanf("%d%d", &x, &y); join(id[x], id[y]); } if(cmd == 2) { scanf("%d%d", &x, &y); //注意要判断下是否在同一颗树上 if(Find(id[x]) != Find(id[y])) { del(x); join(id[x], id[y]); } } if(cmd == 3) { scanf("%d", &x); int r = Find(id[x]); printf("%d %d\n", num[r], sum[r]); } } } return 0; }
相关文章推荐
- UVa 11987 Almost Union-Find(支持删除操作的并查集)
- UVA 11987 Almost Union-Find 并查集的删除操作 懒惰标记
- UVA 11987 Almost Union-Find(有删除操作的并查集)
- uva 11987 Almost Union-Find(带删除操作的并查集)
- uva 11987 Almost Union-Find(带删除操作的并查集)
- UVA 11987 Almost Union-Find (带权并查集的操作及并查集的删除操作)
- UVa-11987 Almost union-find(带删除操作的并查集)
- UVA 11987 Almost Union-Find(带有删除操作的并查集)
- 并查集(删除) UVA 11987 Almost Union-Find
- UVA 11987 Almost Union-Find(并查集的删除)
- UVA11987 - Almost Union-Find (并查集带删除)
- uva11987 Almost Union-Find(可删除元素的并查集)
- UVA 11987 Almost Union-Find 并查集节点删除
- UVA - 11987 Almost Union-Find(带删除的并查集)
- UVA - 11987 Almost Union-Find (并查集的节点删除)
- UVA - 11987 Almost Union-Find[并查集 删除]
- UVA - 11987 Almost Union-Find(带删除的并查集)
- 11987 - Almost Union-Find(并查集删除操作)
- UVA 11987 Almost Union-Find(带删除的并查集)
- UVa 11987 Almost Union-Find(带权并查集)