洛谷 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\n",ans[i]); 51 return 0; 52 }