题目链接:
题意:给出一个图。每次删掉一个点,求删掉之后连通块个数。
思路:正着做不好做,我们反正想,那么题目就变成每次添加一个点(其实就是添加若干条边)之后连通块个数。这就可以使用并查集了。。
vector<int> g[N];int n,m,Q,a[N],s[N],sz[N],h[N],ans[N];int find(int x){ if(s[x]!=x) s[x]=find(s[x]); return s[x];}int sum;void Union(int x,int y){ x=find(x); y=find(y); if(x!=y) { sum--; if(sz[x]<sz[y]) { sz[y]+=sz[x]; s[x]=y; } else { sz[x]+=sz[y]; s[y]=x; } }}int main(){ RD(n,m); int i,j,k,u,v; FOR1(i,m) { RD(u,v); g[u].pb(v),g[v].pb(u); } FOR0(i,n) s[i]=i,sz[i]=1; RD(Q); FOR1(i,Q) RD(a[i]),h[a[i]]=1; sum=n; FOR0(i,n) if(!h[i]) FOR0(j,SZ(g[i])) if(!h[g[i][j]]) { Union(i,g[i][j]); } int x=Q; FORL1(i,Q) { ans[i]=sum-x; x--; h[a[i]]=0; FOR0(j,SZ(g[a[i]])) if(!h[g[a[i]][j]]) { Union(a[i],g[a[i]][j]); } } PR(sum); FOR1(i,Q) PR(ans[i]); return 0;}