洛谷 1197 [JSOI2008]星球大战

【题解】

  把询问离线,倒着加点,并查集维护连通性即可。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<vector>
 5 #define LL long long
 6 #define rg register
 7 #define N 400010
 8 using namespace std;
 9 int n,m,k,cnt,tot,last[N],fa[N],q[N],ans[N];
10 bool v[N];
11 struct edge{int to,pre;}e[N<<1];
12 inline int read(){
13     int k=0,f=1; char c=getchar();
14     while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
15     while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
16     return k*f;
17 }
18 int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
19 int main(){
20     n=read(); m=read();
21     for(rg int i=1;i<=n;i++) fa[i]=i;
22     for(rg int i=1;i<=m;i++){
23         int u=read()+1,v=read()+1;
24         e[++tot]=(edge){u,last[v]}; last[v]=tot;
25         e[++tot]=(edge){v,last[u]}; last[u]=tot;
26     }
27     k=read();
28     for(rg int i=1;i<=k;i++) v[q[i]=read()+1]=1;
29     for(rg int now=1;now<=n;now++)if(!v[now]){
30         cnt++;
31         for(rg int i=last[now],to;i;i=e[i].pre)if(!v[to=e[i].to]){
32             if(find(now)!=find(to)){
33                 fa[find(now)]=find(to);
34                 cnt--;
35             }
36         }
37     }
38     ans[k+1]=cnt;
39     for(rg int j=k;j;j--){
40         int now=q[j];
41         cnt++; v[now]=0;
42         for(rg int i=last[now],to;i;i=e[i].pre)if(!v[to=e[i].to]){
43             if(find(now)!=find(to)){
44                 fa[find(now)]=find(to);
45                 cnt--;
46             }
47         }
48         ans[j]=cnt;
49     }
50     for(rg int i=1;i<=k+1;i++) printf("%d
",ans[i]);
51     return 0;
52 }
原文地址:https://www.cnblogs.com/DriverLao/p/9854215.html