POJ 3908 Quick answer
原题链接:http://poj.org/problem?id=3908
这道题实际上问的是:如何在并查集上删除一个节点但保持连通性(可删节点并查集)。其做法是新开一个pos[]数组,其初始化pos[i]=i,第k次删除节点那么pos[i] = n + k(实际上开辟了一个新节点,并用原节点和新节点做映射),以后再次访问节点 i 的时候用的是pos[i]。
1 #include <stdio.h> 2 #include <string.h> 3 const int maxn = 50000 + 5; 4 5 int f[maxn]; 6 int pos[maxn]; 7 int n; 8 9 int find(int x) 10 {return (f[x] == x) ? x : f[x] = find(f[x]);} 11 12 void init() 13 { 14 for(int i = 1; i < maxn ; i++) 15 f[i] = i, pos[i] = i; 16 } 17 18 void union_set(int a, int b) 19 { 20 int x = find(a); 21 int y = find(b); 22 if(x != y) 23 f[x] = y; 24 } 25 26 int main() 27 { 28 int a, b, yes, no; 29 char s[5]; 30 while(scanf("%d", &n) != EOF && n) 31 { 32 init(); 33 yes = no = 0; 34 int k = n; 35 while(1) 36 { 37 scanf("%s", s); 38 if(s[0] == 'c') 39 { 40 scanf("%d %d", &a, &b); 41 union_set(pos[a], pos[b]); 42 } 43 else if(s[0] == 'd') 44 { 45 scanf("%d", &a); 46 pos[a] = ++k; 47 } 48 else if(s[0] == 'q') 49 { 50 scanf("%d %d", &a, &b); 51 if(find(pos[a]) == find(pos[b])) 52 yes++; 53 else 54 no++; 55 } 56 } 57 else if(s[0] == 'e') 58 break; 59 } 60 printf("%d , %d\n", yes, no); 61 } 62 return 0; 63 }