1. 程式人生 > >並查集中的合併、刪除操作

並查集中的合併、刪除操作

思路:在一般的並查集操作中設立虛父親節點,當刪除x的時候,不是真的刪除x,而是通過一個對映,即令tmp[x] = cnt, parent[cnt] = cnt;這樣x就從原來的集合中獨立出來了,而我們每次合併x,y的時候,只需合併tmp[x], tmp[y]就可以了。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <set>
 6 using namespace std;
 7
8 const int MAXN = (2000000 +100); 9 int parent[MAXN], tmp[MAXN]; 10 bool mark[MAXN]; 11 int N, M, cnt; 12 13 void Init() 14 { 15 for (int i = 0; i < N; i++) { 16 parent[i] = tmp[i] = i; 17 } 18 } 19 20 int Find(int x) 21 { 22 if (parent[x] == x) { 23 return parent[x]; 24 }
25 return parent[x] = Find(parent[x]); 26 } 27 28 void Union(int x, int y) 29 { 30 int r1 = Find(x), r2 = Find(y); 31 if (r1 == r2) return; 32 if (r1 < r2) parent[r1] = r2; 33 else parent[r2] = r1; 34 } 35 36 int main() 37 { 38 int t = 1; 39 while (~scanf("%d %d", &N, &M)) {
40 if (N == 0 && M == 0) break; 41 Init(); 42 cnt = N; 43 while (M--) { 44 char str[2]; 45 int x, y; 46 scanf("%s", str); 47 if (str[0] == 'M') { 48 scanf("%d %d", &x, &y); 49 Union(tmp[x], tmp[y]); 50 } else if (str[0] == 'S') { 51 scanf("%d", &x); 52 parent[cnt] = cnt; 53 tmp[x] = cnt; 54 cnt++; 55 } 56 } 57 memset(mark, false, sizeof(mark)); 58 int ans = 0; 59 for (int i = 0; i < N; i++) { 60 if (!mark[Find(tmp[i])]) { 61 ans++; 62 mark[Find(tmp[i])] = true; 63 } 64 } 65 printf("Case #%d: %d\n", t++, ans); 66 } 67 return 0; 68 }
View Code