BZOJ 1015 星球大战 并查集+离线

   这道题说来真是艰辛,从一开始的RE,到RE,到刚刚的WA,再到AC。 这只能说明我进步的历程,还有我需要不断的加强努力。这道题思路不难,从很久前在黑书中并查集一节就能找到解题的踪影,因为并查集只能并,分不了,所以我们就得离线,倒过来写。只不过这道题真的得审好题目,它问的是剩下的星球中有多少个连通分量,不要搞错了。大概就是这个样子了,加油。

 1 #include<cstdio>
 2 #include<iostream>
 3 #define rep(i,j,k) for(int i= j; i <=k; i++)
 4 #define down(i,j,k) for(int i = j; i >= k; i--)
 5 #define maxn 200005
 6 using namespace std;
 7 
 8 int read()
 9 {
10     int s = 0, t = 1; char c = getchar();
11     while( !isdigit(c) ){
12         if( c == '-' ) t = -1; c = getchar();
13     }
14     while( isdigit(c) ){
15         s = s * 10 + c - '0'; c = getchar();
16     }
17     return s * t;
18 }
19 
20 int fa[maxn],rank[maxn];
21 int find(int x)
22 {
23     return x == fa[x] ? x : fa[x] = find(fa[x]);
24 }
25 
26 int bing(int x,int y)
27 {
28     if( rank[x] > rank[y] ) fa[y] = x;
29     else fa[x] = y;
30 }
31 
32 struct edge{
33 int to; edge* next;
34 };
35 edge *head[maxn*2], *pt, edges[maxn*2];
36 
37 void add_edge(int x,int y)
38 {
39     pt->to = x, pt->next = head[y], head[y] = pt++;
40     pt->to = y, pt->next = head[x], head[x] = pt++;
41 }
42 
43 int q[maxn*2]; bool used[maxn*2] = {0};
44 int ans[maxn*2];
45 
46 int main()
47 {
48     pt = edges; int n = read(), m = read();
49     rep(i,1,n+1) fa[i] = i;  
50     rep(i,1,m){
51         int u = read(), v = read();
52         add_edge(u,v);
53     }
54     int k = read();
55     rep(i,1,k){
56         q[i] = read();
57         used[q[i]] = 1;
58     }
59     int tot = 0;
60     rep(i,0,n-1){
61         if( !used[i] ){
62             tot++;
63             for(edge*e = head[i]; e; e=e->next){
64                 int to = e->to;
65                 if( !used[to] ){
66                     int x = find(i), y = find(to);
67                     if( x != y ){
68                         bing(x,y);
69                         tot--;
70                     }
71                 }
72             }
73         }
74     }
75     ans[k+1] = tot;
76     down(i,k,1){
77         int x = q[i];
78         used[x] = 0; tot++;
79         for(edge*e = head[x]; e; e=e->next){
80             int to = e->to;
81             if( !used[to] ){
82                 int xx = find(x), xy = find(to);
83                 if( xx != xy ){
84                     bing(xx,xy); tot--; 
85                 }
86             }
87         }
88         ans[i] = tot;
89     }
90     rep(i,1,k+1) printf("%d\n", ans[i]);
91     return 0;
92 }

 

posted on 2015-12-31 23:11  83131  阅读(116)  评论(0编辑  收藏  举报

导航