[bzoj1015] [JSOI2008]星球大戰starwar
阿新 • • 發佈:2019-02-05
out getchar() 由於 c++ getch \n 遠的 sample 帝國
這兩個星球在同一個連通塊中)。
的連通塊個數。
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
Solution
倒著做,並查集維護連通性,記個全局的答案就好了。
#include<bits/stdc++.h> using namespace std; void read(int &x) { x=0;int f=1;char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f; for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f; } #define write(x) printf("%d\n",x) const int maxn = 2e5+10; int s[maxn],n,m,q,head[maxn],tot,fa[maxn],ans,res[maxn],vis[maxn]; struct edge{int to,nxt;}e[maxn<<1]; void add(int u,int v) {e[++tot]=(edge){v,head[u]},head[u]=tot;} void ins(int u,int v) {add(u,v),add(v,u);} int find(int x) {return fa[x]==x?x:fa[x]=find(fa[x]);} void insert(int x) { ans++; for(int i=head[x];i;i=e[i].nxt) if(vis[e[i].to]) { int u=find(x),v=find(e[i].to); if(u==v) continue; else fa[u]=v,ans--; } } int main() { read(n),read(m); for(int i=1,x,y;i<=m;i++) read(x),read(y),ins(x+1,y+1); for(int i=1;i<=n;i++) vis[i]=1,fa[i]=i; read(q);for(int i=1;i<=q;i++) read(s[i]),s[i]++,vis[s[i]]=0; for(int x=1;x<=n;x++) if(vis[x]) insert(x);res[q]=ans; for(int i=q;i;i--) vis[s[i]]=1,insert(s[i]),res[i-1]=ans; for(int i=0;i<=q;i++) printf("%d\n",res[i]); return 0; }
[bzoj1015] [JSOI2008]星球大戰starwar