[luoguP1197] [JSOI2008]星球大战(并查集)

传送门

 

思维!重要的是思维!

题目让删边,然而并查集不好删边(并!查!集!啊)

我们离线处理,从后往前添边,这样并查集就可以用了。

用并查集维护连通块个数即可。

 

——代码

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #define N 400001
 5 
 6 int n, m, k, ans, cnt;
 7 int head[N], to[N << 1], next[N << 1], f[N], a[N], anslist[N];
 8 bool vis[N];
 9 
10 inline int read()
11 {
12     int x = 0, f = 1;
13     char ch = getchar();
14     for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
15     for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
16     return x * f;
17 }
18 
19 inline void add(int x, int y)
20 {
21     to[cnt] = y;
22     next[cnt] = head[x];
23     head[x] = cnt++;
24 }
25 
26 inline int find(int x)
27 {
28     return x == f[x] ? x : f[x] = find(f[x]);
29 }
30 
31 int main()
32 {
33     int i, j, x, y, fx, fy;
34     n = read();
35     m = read();
36     memset(head, -1, sizeof(head));
37     for(i = 1; i <= m; i++)
38     {
39         x = read();
40         y = read();
41         add(x, y);
42         add(y, x);
43     }
44     k = read();
45     for(i = 1; i <= k; i++)
46     {
47         a[i] = read();
48         vis[a[i]] = 1;
49     }
50     ans = n - k;
51     for(i = 0; i < n; i++) f[i] = i;
52     for(x = 0; x < n; x++)
53     {
54         if(vis[x]) continue;
55         for(i = head[x]; i ^ -1; i = next[i])
56         {
57             y = to[i];
58             if(vis[y]) continue;
59             fx = find(x);
60             fy = find(y);
61             if(fx ^ fy) f[fx] = fy, ans--; 
62         }
63     }
64     anslist[k] = ans;
65     for(i = k; i >= 1; i--)
66     {
67         x = a[i];
68         ans++;
69         for(j = head[x]; j ^ -1; j = next[j])
70         {
71             y = to[j];
72             if(vis[y]) continue;
73             fx = find(x);
74             fy = find(y);
75             if(fx ^ fy) f[fx] = fy, ans--;
76         }
77         vis[x] = 0;
78         anslist[i - 1] = ans;
79     }
80     for(i = 0; i <= k; i++) printf("%d\n", anslist[i]);
81     return 0;
82 }
View Code

 

总结:有些需要删边询问连通性之类的题目,可以试试从后往前用并查集添边。

   逆向思维很重要!正着不方便就反着来。

posted @ 2017-06-15 20:54  zht467  阅读(108)  评论(0编辑  收藏  举报