bzoj1015 [JSOI2008]星球大战(离线操作+并查集)
2017-09-04 21:02
363 查看
正着做不好做。。。我们考虑把所有的询问存下来,倒着做,每次恢复一颗星球,连通块数量一定是单调不升的。每次就相当于合并两个集合了。
#include<cstdio> int const N=400005; struct edge{ int to,next; }data[N<<1]; int n,m,K,fa ,a ,ans ,h ,num=0,sum=0; bool vis ; inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x*f; } inline int find(int x){ return x==fa[x]?x:fa[x]=find(fa[x]); } inline void merge(int x,int y){ int xx=find(x),yy=find(y); if(xx!=yy) fa[xx]=yy,sum--; } int main(){ // freopen("a.in","r",stdin); n=read();m=read(); for(int i=0;i<n;++i) fa[i]=i,vis[i]=true; while(m--){ int x=read(),y=read(); data[++num].to=y;data[num].next=h[x];h[x 4000 ]=num; data[++num].to=x;data[num].next=h[y];h[y]=num; } K=read(); for(int i=1;i<=K;++i) a[i]=read(),vis[a[i]]=false; sum=n-K; for(int x=0;x<n;++x) if(vis[x]) for(int i=h[x];i;i=data[i].next){ int y=data[i].to;if(vis[y]) merge(x,y); } for(int i=K;i>=1;--i){ ans[i]=sum; int x=a[i];vis[x]=true;sum++; for(int j=h[x];j;j=data[j].next){ int y=data[j].to; if(vis[y]) merge(x,y); } } ans[0]=sum; for(int i=0;i<=K;++i) printf("%d\n",ans[i]); return 0; }
相关文章推荐
- 【bzoj1015】【JSOI2008】【星球大战】【并查集+离线】
- 【bzoj1015】【JSOI2008】【星球大战】【并查集+离线】
- BZOJ 1015 [JSOI2008]星球大战——并查集+离线处理
- BZOJ 1015: [JSOI2008]星球大战starwar 并查集 离线维护
- BZOJ1015: [JSOI2008]星球大战starwar 并查集 离线处理
- 【BZOJ1015】【JSOI2008】星球大战 并查集
- [bzoj 1015] [JSOI2008]星球大战starwar:并查集,离线
- 【bzoj1015】【JSOI2008】【星球大战】【starwar】【并查集】
- [bzoj1015][JSOI2008]星球大战——并查集+离线处理
- BZOJ_1015_[JSOI2008]星球大战_并查集
- BZOJ 1015: [JSOI2008]星球大战starwar(并查集求连通块+离线处理)
- bzoj 1015: [JSOI2008]星球大战starwar 并查集+离线处理
- BZOJ_1015_星球大战_[JSOI2008]_(并查集)
- 【bzoj1015】[JSOI2008]星球大战 并查集
- BZOJ 1015 JSOI2008 星球大战 starwar 并查集
- [Bzoj1015][JSOI2008]星球大战starwar(并查集)(离线处理)
- bzoj 1015: [JSOI2008]星球大战starwar【并查集】
- BZOJ 1015: [JSOI2008]星球大战starwar【并查集】
- 【BZOJ 1015】【JSOI 2008】星球大战starwar【并查集】
- bzoj1015: [JSOI2008]星球大战starwar(并查集)