bzoj 1015 星球大战starwar

题目大意:

一个n个点m条边的无向图,现在依次删除k个点及它们的边

求开始有几个联通块及每次删除一个点后的联通块

思路:

直接做不太好做

所以我们可以把删除离线下来

先把不被删的点之间都连起来,联通块个数即为最后一次的输出

然后倒序加入每个被删的点

再倒序输出即可

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<cstdlib>
 6 #include<cstring>
 7 #include<queue>
 8 #include<map>
 9 #include<vector>
10 #define ll long long
11 #define inf 2147483611
12 #define MAXN 400100
13 using namespace std;
14 inline int read()
15 {
16     int x=0,f=1;char ch=getchar();
17     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
18     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
19     return x*f;
20 }
21 int n,m,nxt[MAXN],to[MAXN],fst[MAXN],f[MAXN],cnt,ans[MAXN],q[MAXN],hsh[MAXN],k;
22 void add(int u,int v) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v;}
23 int find(int x) {return x==f[x]?x:f[x]=find(f[x]);}
24 int main()
25 {
26     n=read(),m=read();
27     int a,b;
28     memset(ans,0xff,sizeof(ans));
29     for(int i=1;i<=m;i++) {a=read()+1,b=read()+1;add(a,b);add(b,a);}
30     int Q=read();
31     for(int i=1;i<=Q;i++) q[i]=read()+1,hsh[q[i]]=1;
32     for(int i=1;i<=n;i++) f[i]=i;
33     int num=0;
34     for(int i=1;i<=n;i++)
35     {
36         if(hsh[i]) continue;
37         num++;k=find(i);
38         for(int j=fst[i];j;j=nxt[j]) if(!hsh[to[j]]) if(find(to[j])!=k) f[find(to[j])]=k,num--;
39     }
40     ans[Q+1]=num;
41     while(Q)
42     {
43         num++;k=find(q[Q]);
44         for(int j=fst[q[Q]];j;j=nxt[j]) if(!hsh[to[j]]) if(find(to[j])!=k) f[find(to[j])]=k,num--;
45         hsh[q[Q]]=0;
46         ans[Q]=num;Q--;
47     }
48     for(int i=1;i;i++) {if(ans[i]==-1) break;printf("%d\n",ans[i]);}
49 }
View Code

 

posted @ 2017-11-24 20:13  jack_yyc  阅读(189)  评论(0编辑  收藏  举报