bzoj 1015 并查集
代码:
//这题可以反着想,把要去掉的点倒着处理变成往图中一个一个的加点,然后用并查集处理联通快就好了。 #include<iostream> #include<cstdio> #include<cstring> #include<vector> using namespace std; const int MAXN=400000; int fa[MAXN+10],des[MAXN+10],ans[MAXN+10],head[MAXN+10],n,m,k,tot; bool use[MAXN+10]; struct Edge { int to,next; }edge[MAXN*2+10]; void init() { tot=0; for(int i=0;i<n;i++){ fa[i]=i; use[i]=1; head[i]=-1; } } void add(int x,int y) { edge[tot].to=y; edge[tot].next=head[x]; head[x]=tot++; } int find(int x) {return x==fa[x]?x:fa[x]=find(fa[x]);} int main() { scanf("%d%d",&n,&m); init(); for(int i=1;i<=m;i++){ int x,y; scanf("%d%d",&x,&y); add(x,y); add(y,x); } scanf("%d",&k); for(int i=1;i<=k;i++){ scanf("%d",&des[i]); use[des[i]]=0; } int tmp=0; for(int i=0;i<n;i++){ if(!use[i]) continue; tmp++; for(int j=head[i];j!=-1;j=edge[j].next){ int x=edge[j].to; if(!use[x]) continue; int ii=find(i),xx=find(x); if(ii!=xx){ fa[ii]=xx; tmp--; } } } ans[k]=tmp; for(int i=k;i>=1;i--){ int x=des[i]; use[x]=1; tmp++; for(int j=head[x];j!=-1;j=edge[j].next){ int y=edge[j].to; if(!use[y]) continue; int xx=find(x),yy=find(y); if(xx!=yy){ fa[xx]=yy; tmp--; } } ans[i-1]=tmp; } for(int i=0;i<=k;i++) printf("%d\n",ans[i]); return 0; }