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

bzoj1015 [JSOI2008]星球大戰starwar

read space 一點 ber closed turn 任務 while cst

1015: [JSOI2008]星球大戰starwar

2017-09-02


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

此題甚是有趣,刪點求連通塊的個數.每刪一點求一次. 一看到連通塊就想到並查集.....然而並不知道怎麽拆掉只有一層的樹(縮點後的並查集),使其分離連通塊. 但是如果反過來,從不用刪的點的塊開始連,刪點就是反向加點&&邊求連通塊數量,再倒敘輸出可以了; 可愛的讀入優化把輸入的點轉到1-N很有趣poi... 技術分享
#include<iostream>
#include
<cstdlib> #include<cstdio> #include<algorithm> using namespace std; const int maxn=500007; int read(){ int an=0,f=1;char ch=getchar(); while(!(0<=ch&&ch<=9)){if(ch==-)f=-1;ch=getchar();} while(0<=ch&&ch<=9){an=an*10+(ch-0);ch=getchar();} return f*an+1; } int n,m,T,sum,ans[maxn],tot; int x,y; bool used[maxn]; bool pd[maxn]; int sh[maxn],f[maxn],fa[maxn]; struct saber{ int kkk,to; }b[maxn]; void add(int x,int y){ sum++; b[sum].kkk=f[x]; f[x]=sum; b[sum].to=y; } int found(int x){ if(x!=fa[x])fa[x]=found(fa[x]); return fa[x]; } void ad(int x){ int p=found(x); for(int i=f[x];i;i=b[i].kkk){ if(used[b[i].to]){ int q=found(b[i].to); if(p!=q){fa[q]=p;tot--;} } } } int main(){ n=read()-1;m=read()-1; for(int i=1;i<=n;i++)fa[i]=i; for(int i=1;i<=m;i++){ x=read();y=read(); add(x,y);add(y,x); } T=read()-1; for(int i=1;i<=T;i++){ sh[i]=read(); pd[sh[i]]=1; } for(int i=1;i<=n;i++){ if(!pd[i]){ ad(i); used[i]=1; tot++; } } ans[T+1]=tot; for(int i=T;i>=1;i--){ tot++; ad(sh[i]); ans[i]=tot; used[sh[i]]=1; } for(int i=1;i<=T+1;i++)printf("%d\n",ans[i]); return 0; }
star_war

by:s_a_b_e_r


bzoj1015 [JSOI2008]星球大戰starwar