倒着处理删点,就变成了加点,于是并查集。
#include<cstdio> using namespace std; #define N 400001 int fa[N],kill[N],rank[N],n,m,q; bool hav[N]; int next[N],first[N],v[N],en,x,y,anss[N],cnt; void AddEdge(int U,int V) { v[++en]=V; next[en]=first[U]; first[U]=en; } int find(int x) { if(x==fa[x]) return x; fa[x]=find(fa[x]); return fa[x]; } void Union(int U,int V) { --cnt; if(rank[U]<rank[V]) fa[U]=V; else { fa[V]=U; if(rank[U]==rank[V]) ++rank[U]; } } int main() { scanf("%d%d",&n,&m); cnt=n; for(int i=0;i<n;++i) fa[i]=i; for(int i=1;i<=m;++i) { scanf("%d%d",&x,&y); AddEdge(x,y); AddEdge(y,x); } scanf("%d",&q); for(int i=1;i<=q;++i) { scanf("%d",&kill[i]); hav[kill[i]]=1; } for(int i=0;i<n;++i) if(!hav[i]) for(int j=first[i];j;j=next[j]) if(!hav[v[j]]) { int f1=find(i),f2=find(v[j]); if(f1!=f2) Union(f1,f2); } for(int i=q;i>=1;--i) { anss[i]=cnt-i; for(int j=first[kill[i]];j;j=next[j]) if(!hav[v[j]]) { int f1=find(kill[i]),f2=find(v[j]); if(f1!=f2) Union(f1,f2); } hav[kill[i]]=0; } anss[0]=cnt; for(int i=0;i<=q;++i) printf("%d ",anss[i]); return 0; }