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 }
View Code

 

posted @ 2013-05-24 18:43  芒果布丁  阅读(273)  评论(0编辑  收藏  举报