BZOJ - 1015【並查集】

1015: [JSOI2008]星球大戰starwar

Time Limit: 3 Sec  Memory Limit: 162 MB
Submit: 5721  Solved: 2639
[Submit][Status][Discuss]

Description

  好久之前,在一個遙遠的星系,一個黑暗的帝國靠着它的超級武器統治者整個星系。某一天,憑着一個偶然的
機遇,一支反抗軍摧毀了帝國的超級武器,並攻下了星系中幾乎全部的星球。這些星球經過特殊的以太隧道互相直
接或間接地鏈接。 但好景不長,很快帝國又從新造出了他的超級武器。憑藉這超級武器的力量,帝國開始有計劃
地摧毀反抗軍佔領的星球。因爲星球的不斷被摧毀,兩個星球之間的通信通道也開始不可靠起來。如今,反抗軍首
領交給你一個任務:給出原來兩個星球之間的以太隧道連通狀況以及帝國打擊的星球順序,以儘可能快的速度求出每
一次打擊以後反抗軍佔據的星球的連通快的個數。(若是兩個星球能夠經過現存的以太通道直接或間接地連通,則
這兩個星球在同一個連通塊中)。php

Input

  輸入文件第一行包含兩個整數,N (1  < =  N  < =  2M) 和M (1  < =  M  < =  200,000),分別表示星球的
數目和以太隧道的數目。星球用 0 ~ N-1的整數編號。接下來的M行,每行包括兩個整數X, Y,其中(0 < = X <>
Y 表示星球x和星球y之間有「以太」隧道,能夠直接通信。接下來的一行爲一個整數k,表示將遭受攻擊的星球的
數目。接下來的k行,每行有一個整數,按照順序列出了帝國軍的攻擊目標。這k個數互不相同,且都在0到n-1的範
圍內。ios

Output

  輸出文件的第一行是開始時星球的連通塊個數。接下來的N行,每行一個整數,表示通過該次打擊後現存星球
的連通塊個數。ide

Sample Input

8 13
0 1
1 6
6 5
5 0
0 6
1 2
2 3
3 4
4 5
7 1
7 2
7 6
3 6
5
1
6
3
5
7

Sample Output

1
1
1
2
3
3

 

題解:逆向並查集便可,學習了新姿式,不用每次去getfa求聯通塊數目,只須要每次新加點的時候 num++,而後合併的時候num--便可;學習

代碼:spa

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <cstdio>
 5 #include <bitset>
 6 #include <vector>
 7 #include <queue>
 8 #include <stack>
 9 #include <cmath>
10 #include <list>
11 #include <set>
12 #include <map>
13 #define rep(i,a,b) for(int i = a;i <= b;++ i)
14 #define per(i,a,b) for(int i = a;i >= b;-- i)
15 #define mem(a,b) memset((a),(b),sizeof((a)))
16 #define FIN freopen("in.txt","r",stdin)
17 #define FOUT freopen("out.txt","w",stdout)
18 #define IO ios_base::sync_with_stdio(0),cin.tie(0)
19 #define mid ((l+r)>>1)
20 #define ls (id<<1)
21 #define rs ((id<<1)|1)
22 #define N 400010
23 #define INF 0x3f3f3f3f
24 #define INFF ((1LL<<62)-1)
25 using namespace std;
26 typedef long long LL;
27 typedef pair<int, int> PIR;
28 const double eps = 1e-8;
29  
30 int n, m, u, v, t, k[N], f[N], ans[N];
31 vector <int> G[N];
32 bool vis[N];
33 int getfa(int x){
34     return f[x] == x ? x : f[x] = getfa(f[x]);
35 }
36 int main()
37 {
38     //FIN;
39     scanf("%d %d", &n, &m);
40     rep(i, 1, m){ 
41         scanf("%d %d", &u, &v);
42         G[u].push_back(v);
43         G[v].push_back(u);
44     }
45     scanf("%d", &t);
46     rep(i, 1, t)    { scanf("%d", &k[i]); vis[k[i]] = true; }
47     rep(i, 0, n)    f[i] = i;
48  
49     int res = n-t;
50     rep(i, 0, n-1){
51         if(vis[i])  continue;
52         int x = getfa(i);
53         rep(j, 0, (int)G[i].size()-1){
54             if(vis[G[i][j]])    continue;
55             int y = getfa(G[i][j]);
56             if(x != y)  { f[y] = x; res--; }
57         }
58     }
59     /*int res = 0;
60     rep(i, 0, n-1)  { if(!vis[i] && getfa(i) == i)  res++; }*/
61     per(i, t, 0){
62         ans[i] = res++;
63         vis[k[i]] = false;
64         int x = getfa(k[i]);
65         rep(j, 0, (int)G[k[i]].size()-1){
66             if(vis[G[k[i]][j]]) continue;
67             int y = getfa(G[k[i]][j]);
68             if(x != y){ 
69                 f[y] = x;
70                 res--;
71             }
72         }
73     }
74     rep(i, 0, t)    printf("%d\n", ans[i]);
75     return 0;
76 }
View Code
相關文章
相關標籤/搜索