1. 程式人生 > >P1197 [JSOI2008]星球大戰

P1197 [JSOI2008]星球大戰

hold class 不能 lba 順序 spa 情況 truct -c

P1197 [JSOI2008]星球大戰

題目描述

很久以前,在一個遙遠的星系,一個黑暗的帝國靠著它的超級武器統治者整個星系。某一天,憑著一個偶然的機遇,一支反抗軍摧毀了帝國的超級武器,並攻下了星系中幾乎所有的星球。這些星球通過特殊的以太隧道互相直接或間接地連接。

但好景不長,很快帝國又重新造出了他的超級武器。憑借這超級武器的力量,帝國開始有計劃地摧毀反抗軍占領的星球。由於星球的不斷被摧毀,兩個星球之間的通訊通道也開始不可靠起來。現在,反抗軍首領交給你一個任務:給出原來兩個星球之間的以太隧道連通情況以及帝國打擊的星球順序,以盡量快的速度求出每一次打擊之後反抗軍占據的星球的連通快的個數。(如果兩個星球可以通過現存的以太通道直接或間接地連通,則這兩個星球在同一個連通塊中)。

輸入輸出格式

輸入格式:

輸入文件第一行包含兩個整數,N (1 <= N <= 2M) 和M (1 <= M <= 200,000),分別表示星球的數目和以太隧道的數目。星球用0~N-1的整數編號。

接下來的M行,每行包括兩個整數X, Y,其中(0<=X<>Y<N),表示星球X和星球Y之間有以太隧道。註意所有的以太隧道都是雙向的。

接下來一行是一個整數K,表示帝國計劃打擊的星球個數。

接下來的K行每行一個整數X,滿足0<=X<N,表示帝國計劃打擊的星球編號。帝國總是按輸入的順序依次摧毀星球的。

輸出格式:

輸出文件的第一行是開始時星球的連通塊個數。

接下來的K行,每行一個整數,表示經過該次打擊後現存星球的連通塊個數。

輸入輸出樣例

輸入樣例#1:
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
輸出樣例#1:
1
1
1
2
3
3

說明

[JSOI2008]

並查集。逆序做,因為並查集是不能修改的。

 1 #include<cstdio>
 2 
 3 const int N = 500100;
 4 struct Edge{
 5     int
to,nxt; 6 }e[N]; 7 int far[N],head[N],t[N],ans[N]; 8 bool v[N]; 9 int n,m,k,cnt,p,s; 10 11 int find(int a) 12 { 13 if(a!=far[a]) far[a] = find(far[a]); 14 return far[a]; 15 } 16 void add(int x,int y) 17 { 18 ++cnt; 19 e[cnt].to = y; 20 e[cnt].nxt = head[x]; 21 head[x] = cnt; 22 } 23 int main() 24 { 25 scanf("%d%d",&n,&m); 26 for(int i=0;i<n;++i) far[i] = i; //從0開始 ,很重要!!! 27 for(int i=1;i<=m;++i) 28 { 29 int x,y; 30 scanf("%d%d",&x,&y); 31 add(x,y); add(y,x); //無向圖 32 } 33 scanf("%d",&k); 34 for(int i=1;i<=k;++i) 35 { 36 scanf("%d",&t[i]); 37 v[t[i]] = true; 38 } 39 s = n-k; 40 for(int i=0;i<n;++i) //找出不會被轟炸的點並連起來 41 { 42 if(!v[i]) 43 for(int j=head[i];j;j=e[j].nxt) 44 if(!v[e[j].to]) 45 { 46 int r1 = find(i); 47 int r2 = find(e[j].to); 48 if(r1 != r2) far[r2] = r1, s--; 49 } 50 } 51 ans[k+1] = s; 52 for(int i=k;i>=1;--i) 53 { 54 int a = t[i]; 55 v[a] = false ; 56 s++; //因為新加了一個點,所以連通塊的個數要加一 57 for(int j=head[a];j;j=e[j].nxt) 58 { 59 int b = e[j].to; 60 if(!v[b]) 61 { 62 int r1 = find(a); 63 int r2 = find(b); 64 if(r1 != r2) far[r2] = r1, s--; 65 } 66 } 67 ans[i] = s; 68 } 69 for(int i=1;i<=k+1;++i) 70 printf("%d\n",ans[i]); 71 return 0; 72 }

P1197 [JSOI2008]星球大戰