1. 程式人生 > >BZOJ-1015: [JSOI2008]星球大戰starwar (並查集)

BZOJ-1015: [JSOI2008]星球大戰starwar (並查集)

discuss lin bsp tchar tar ble names 攻擊 目標

1015: [JSOI2008]星球大戰starwar

Time Limit: 3 Sec Memory Limit: 162 MB
Submit: 6784 Solved: 3180
[Submit][Status][Discuss]

Description

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

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的範
圍內。

Output

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

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

HINT

Source

正著不斷刪點做不了,很巧妙的想法,存入詢問,然後倒著插點進去

 1 #include "bits/stdc++.h"
 2 using namespace std;
 3 typedef long long LL;
 4 const int MAX=4e5+5;
 5 int n,m,K;
 6 int tot,head[MAX],adj[MAX],next[MAX];
7 int fa[MAX],ans[MAX],re[MAX],tt; 8 bool vis[MAX],t[MAX]; 9 inline int read(){ 10 int an=0,x=1;char c=getchar(); 11 while (c<0 || c>9) {if (c==-) x=-1;c=getchar();} 12 while (c>=0 && c<=9) {an=(an<<3)+(an<<1)+c-0;c=getchar();} 13 return an*x; 14 } 15 void addedge(int u,int v){ 16 tot++;adj[tot]=v,next[tot]=head[u],head[u]=tot; 17 } 18 int getfather(int x){return fa[x]==x?x:fa[x]=getfather(fa[x]);} 19 void add(int x){ 20 int tx=getfather(x),ty,i; 21 for (i=head[x];i;i=next[i]){ 22 if (vis[adj[i]]){ 23 ty=getfather(adj[i]); 24 if (tx!=ty) fa[ty]=tx,tt--; 25 } 26 } 27 } 28 int main(){ 29 freopen ("planet.in","r",stdin);freopen ("planet.out","w",stdout); 30 int i,j,u,v; 31 n=read(),m=read();tot=1; 32 for (i=1;i<=m;i++){ 33 u=read(),v=read();u++,v++; 34 addedge(u,v),addedge(v,u); 35 } 36 for (i=1;i<=n;i++) fa[i]=i; 37 K=read(); 38 for (i=1;i<=K;i++){ 39 re[i]=read(),re[i]++; 40 t[re[i]]=true; 41 } 42 for (i=1;i<=n;i++) 43 if (!t[i]){ 44 tt++; 45 add(i); 46 vis[i]=true; 47 } 48 49 ans[K+1]=tt; 50 for (i=K;i>=1;i--){ 51 tt++; 52 add(re[i]); 53 vis[re[i]]=true; 54 ans[i]=tt; 55 } 56 for (i=1;i<=K+1;i++) 57 printf("%d\n",ans[i]); 58 return 0; 59 }

BZOJ-1015: [JSOI2008]星球大戰starwar (並查集)