[JSOI2008]星球大战starwar

[JSOI2008]星球大战starwar

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 





7

Sample Output






3

Hint

 

Source

耒阳大视野(衡阳八中) OJ 1015 , JSOI2008 
并查集

思路:并查集水题,调了30min。。。

并查集不能删除,所以把所有操作倒过来,删除改成加边,就可以AC了

(先把边用图存应该快些)

 1 // It is made by XZZ
 2 #include<cstdio>
 3 #include<algorithm>
 4 using namespace std;
 5 #define rep(a,b,c) for(rg int a=b;a<=c;a++)
 6 #define drep(a,b,c) for(rg int a=b;a>=c;a--)
 7 #define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
 8 #define il inline
 9 #define rg register
10 #define vd void
11 #define t (dis[i])
12 typedef long long ll;
13 il int gi(){
14     rg int x=0;rg char ch=getchar();
15     while(ch<'0'||ch>'9')ch=getchar();
16     while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
17     return x;
18 }
19 const int maxn=400001,maxm=200001<<1;
20 int C[maxn],fa[maxn];
21 int ans[maxn+2];
22 bool yes[maxn];
23 int fir[maxn],id,dis[maxm],nxt[maxm];
24 il vd add(int a,int b){
25     nxt[++id]=fir[a],fir[a]=id,dis[id]=b;
26 }
27 il int hd(int n){
28     rg int r=n,tmp;
29     while(fa[r]^r)r=fa[r];
30     while(n^r)tmp=fa[n],fa[n]=r,n=tmp;
31     return r;
32 }
33 il bool Union(int a,int b){
34     rg int Ha=hd(a),Hb=hd(b);
35     if(Ha==Hb)return 0;
36     fa[Ha]=Hb;return 1;
37 }
38 int main(){
39     rg int n=gi(),m=gi(),a,b;
40     rep(i,1,m)a=gi()+1,b=gi()+1,add(a,b),add(b,a);
41     rg int k=gi(),Ans=n;
42     rep(i,1,k)C[k-i+1]=gi()+1,yes[C[k-i+1]]=1;
43     rep(i,1,n)fa[i]=i;
44     rep(now,1,n)if(!yes[now])erep(i,now)if(!yes[t]&&Union(t,now))--Ans;
45     ans[0]=Ans;
46     rep(now,1,k){
47     erep(i,C[now])if(!yes[t]&&Union(t,C[now]))--Ans;
48     ans[now]=Ans,yes[C[now]]=0;
49     }
50     reverse(ans,ans+1+k);
51     rep(i,0,k)printf("%d
",ans[i]-i);
52     return 0;
53 }
View Code
原文地址:https://www.cnblogs.com/xzz_233/p/7212437.html