代码:
//这题可以反着想,把要去掉的点倒着处理变成往图中一个一个的加点,然后用并查集处理联通快就好了。 #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; }