uva 11987 几乎就是并查集(并查集+一点小技巧)

来源:互联网 发布:淘宝聚划算是什么意思 编辑:程序博客网 时间:2024/06/01 09:18


题意:初始有N个集合,分别为 1 ,2 ,3 .....n。有三种操件
1 p q 合并元素p和q的集合
2 p q 把p元素移到q集合中
3 p 输出p元素集合的个数及全部元素的和。

1、3操作比较简单,关键是2操作,并查集不能删除元素,但是我们要求的结果其实和要删除的元素没有关系,所以我们考虑用一个新的节点代替要删除的元素,用nid表示要删除的元素的新的id,这样我们就可以实现2操作了

代码如下:

#include<cstdio>  #include<cstring>  #include<cmath>  #include<cstdlib>  #include<iostream>  #include<algorithm>  #include<vector>  #include<map>  #include<queue>  #include<stack> #include<string>#include<map> #include<set>using namespace std;  #define LL long long  const int maxn = 200000 + 5;const int INF = 1000000000;//freopen("input.txt", "r", stdin);int num[maxn], sumu[maxn], pa[maxn], nid[maxn];void init(int n) {for(int i = 1; i <= n; i++) { pa[i] = i; num[i] = 1; sumu[i] = i; nid[i] = 0;}}int find(int x) {if(x != pa[x]) return pa[x] = find(pa[x]);return x;}int main() {int n, m;while(scanf("%d%d", &n, &m) != EOF) {init(n);int cnt = n + 1;for(int i = 1; i <= m; i++) {int cmd; scanf("%d", &cmd);switch(cmd) {case 1: {int p, q; scanf("%d%d", &p, &q);intu = nid[p] == 0? find(p) : find(nid[p]); intv = nid[q] == 0? find(q) : find(nid[q]);if(u != v) {pa[u] = v;sumu[v] += sumu[u];num[v] += num[u];}break;}case 2: {int p, q; scanf("%d%d", &p, &q);intu = nid[p] == 0? find(p) : find(nid[p]); intv = nid[q] == 0? find(q) : find(nid[q]);if(u != v) {nid[p] = cnt++;pa[nid[p]] = v;sumu[v] += p; sumu[u] -= p;num[v]++; num[u]--;}break;}case 3: {int p, ans1, ans2; scanf("%d", &p);if(!nid[p]) ans1 = num[find(p)], ans2 = sumu[find(p)];else ans1 = num[find(nid[p])], ans2 = sumu[find(nid[p])];printf("%d %d\n", ans1, ans2);break;}}}}return 0;}


0 0
原创粉丝点击