题意:
这里有N个数编号1 ~N,开始每个数各自在一个集合里面,然后有三种命令:
1 P Q :把 P 所在的集合和 Q 所在的集合合并,如果已经在一个集合里面了就忽视
2 P Q : 把 P 这个元素从它所在的集合里面拿出来放到 Q 里面,,如果已经在一个集合里面了就忽视
3 P :询问 P 所在集合元素的 个数 和P所在集合元素的 和。
思路:
对于命令 1 直接合并就好了,用cnt[]数组代表元素个数,sum[]数组代表元素的和,合并的同时维护数组即可,对于命令 2 ,需要好好想一想,如果 P 不是根节点还好,如果是根节点的话,直接合并难免会出问题,所以可以重新开一个数组,d[],用来代表节点的编号,刚开始 d[i]存的都是i;当命令2 时 我们可以在题目所给的节点之外重新找个节点(1 ~N之外),比如 N +1.让 d[P] = N +1;(第二次就是N+2,总之就是重新找个不存在的节点来覆盖当前这个节点。)这样原来集合里面的那个 P 就失效了,我们合并 d[P] 和 d[Q]就好了,因为原来集合里面的 d[P] 节点已经不叫 P了,而是叫 N+1了,这样我们就不用考虑是否是根节点了。命令3直接查询就好了~~~具体看代码、、、、、
代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cmath> 6 #include <cctype> 7 #include <algorithm> 8 using namespace std; 9 const int MAXN =1e5 + 3; 10 int pre[MAXN*2],cnt[MAXN*2],sum[MAXN*2],d[MAXN*2];//依次为父节点数组,个数数组,求和数组,代号数组 11 12 int Find(int x) 13 { 14 int r = x; 15 while(pre[r] != r) 16 { 17 r = pre[r]; 18 } 19 int i = x,j; 20 while(pre[i] != r) 21 { 22 j = i; 23 i = pre[i]; 24 pre[j] = r; 25 } 26 return r; 27 } 28 void Mix(int a,int b) 29 { 30 int fa = Find(a),fb = Find(b); 31 if(fa != fb) 32 { 33 pre[fa] = fb; 34 sum[fb] += sum[fa]; //合并的同时维护两个数组 35 cnt[fb] += cnt[fa]; 36 } 37 } 38 void make_set(int n) //初始化初始化初始化 39 { 40 for(int i = 1; i <= n; i++){ 41 pre[i] = i; 42 sum[i] = i; 43 cnt[i] = 1; 44 d[i] = i; 45 } 46 } 47 48 int main() 49 { 50 //freopen("in.cpp","r",stdin); 51 void debug(int n); 52 int n,m; 53 while(~scanf("%d%d",&n,&m)) 54 { 55 make_set(n); 56 int temp = n + 1; 57 while(m--) 58 { 59 int order; 60 scanf("%d",&order); 61 if(order == 1) //命令一 直接合并就好了 62 { 63 int p,q; 64 scanf("%d%d",&p,&q); 65 Mix(d[p],d[q]); 66 // debug(n); 67 } 68 else if(order == 2) //命令二 69 { 70 int p,q; 71 scanf("%d%d",&p,&q); 72 int fp = Find(d[p]),fq = Find(d[q]); 73 if(fp != fq) { 74 sum[fp] -= p; //更新原来的集合数组 75 cnt[fp] --; 76 d[p] = temp++; //新来了一个点代号 temp ,并覆盖原来的那个点,原来d[p] = p 现在等于 trmp 了 77 sum[d[p]] = p; //新来这个点的 sum 数组初始化 78 cnt[d[p] ]= 1; //cnt 数组初始化 79 pre[d[p]] = d[p]; //pre 数组初始化 80 } 81 Mix(d[p],d[q]); //直接合并就好了 82 // debug(n); 83 } 84 else if(order == 3) 85 { 86 int p; 87 scanf("%d",&p); 88 int fp = Find(d[p]); 89 printf("%d %d ",cnt[fp],sum[fp]); 90 } 91 } 92 } 93 return 0; 94 }