標籤:任務 star ios set 破壞 log 開始 維護 之間
Description
很久以前,在一個遙遠的星系,一個黑暗的帝國靠著它的超級武器統治者整個星系。某一天,憑著一個偶然的機遇,一支反抗軍摧毀了帝國的超級武器,並攻下了星系中幾乎所有的星球。這些星球通過特殊的以太隧道互相直接或間接地串連。 但好景不長,很快帝國又重新造出了他的超級武器。憑藉這超級武器的力量,帝國開始有計劃地摧毀反抗軍佔領的星球。由於星球的不斷被摧毀,兩個星球之間的通訊通道也開始不可靠起來。現在,反抗軍首領交給你一個任務:給出原來兩個星球之間的以太隧道連通情況以及帝國打擊的星球順序,以盡量快的速度求出每一次打擊之後反抗軍佔據的星球的連通快的個數。(如果兩個星球可以通過現存的以太通道直接或間接地連通,則這兩個星球在同一個連通塊中)。
Input
第一行包含兩個整數N (2 ≤ N ≤ 2M)和M (1 ≤ M ≤ 200,000),分別表示星球的數目和“以太”隧道的數目。星球用0到N – 1的整數編號。
接下來的M行,每行包含兩個整數X和Y (0 ≤ X ≠ Y < N),表示星球X和星球Y之間有“以太”隧道,可以直接通訊。
接下來的一行包含一個整數K,表示將遭受攻擊的星球的數目。
接下來的K行,每行一個整數,按照順序列出了帝國軍的攻擊目標。這K個數互不相同,且都在0到N – 1的範圍內。
Output
第一行是開始時星球的連通塊個數。接下來的N行,每行一個整數,表示經過該次打擊後現存星球的連通塊個數。
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
題解:這個題目,直接線上維護聯通塊的數量是不可能的,所以我們考慮倒過來,先把所有的星球破壞好,統計一下數目,然後一個一個加星球,用並查集維護一下數目就可以了。具體實現看代碼。 代碼:
#include<iostream>#include<stdlib.h>#include<algorithm>#include<cstring>#include<stdio.h>const int MAXN=201000;using namespace std;bool b[2*MAXN],bb[MAXN*2];int qu[2*MAXN],fa[2*MAXN],ans[MAXN*2];int n,m,q,num=0;struct edge{ int first,next,to;}a[MAXN*2];struct edge2{ int from,to; void read(){ scanf("%d%d",&from,&to); }}e[MAXN*2]; void cl(){ memset(b,0,sizeof(b)); memset(bb,0,sizeof(bb)); memset(qu,0,sizeof(qu)); memset(fa,0,sizeof(fa)); memset(ans,0,sizeof(ans));} int find(int now){ if(fa[now]!=now) fa[now]=find(fa[now]); return fa[now];} void hebin(int x,int y){ int xx=find(x),yy=find(y); fa[xx]=yy;} void addedge(int from,int to){ a[++num].to=to; a[num].next=a[from].first; a[from].first=num;} int main(){ cl(); scanf("%d%d",&n,&m); for(int i=0;i<=n-1;i++) fa[i]=i; for(int i=1;i<=m;i++){ int x,y; e[i].read(); addedge(e[i].from,e[i].to),addedge(e[i].to,e[i].from); } scanf("%d",&q); for(int i=1;i<=q;i++){ scanf("%d",&qu[i]); b[qu[i]]=1; } for(int i=1;i<=m;i++){ int x=e[i].from,y=e[i].to; if(b[x]||b[y]) continue; if(find(x)!=find(y)) hebin(x,y); } for(int i=0;i<=n-1;i++) find(i);num=0; for(int i=0;i<=n-1;i++){ if(b[i]) continue; if(!bb[fa[i]]) bb[fa[i]]=1,num++; } ans[q]=num; for(int j=q;j>=1;j--){ b[qu[j]]=0; num++; for(int i=a[qu[j]].first;i;i=a[i].next){ int to=a[i].to; if(b[to]) continue; if(find(qu[j])!=find(to)){ hebin(qu[j],to); num--; } } ans[j-1]=num; } for(int i=0;i<=q;i++) printf("%d\n",ans[i]);}
[JSOI2008]星球大戰starwar