看到联通块,好像跟并查集、强连通分量有关系吧,仔细一看跟哪些点属于哪些块没关系,只关心联通块数量,那么应该可以用并查集做。继续看,这是一道删边的题,好像很难维护删边,我们又知道并查集是可以维护加边的,那么我们就倒过来做好了。
#include#include #include #define MAXN 400005struct Node{ int u,v;}E[MAXN];struct edge{ int v,next;}G[MAXN];int fa[MAXN],vis[MAXN];int ed[MAXN],ans[MAXN];int head[MAXN];int N,M,K,tot=0;int find(int x){ return x==fa[x]?x:fa[x]=find(fa[x]);}inline void merge(int u,int v){ fa[find(u)] = find(v);}inline void add(int u,int v){ G[++tot].v = v ;G[tot].next = head[u];head[u] = tot;}int main(){ scanf("%d%d",&N,&M); for(register int i=0;i =1;--i){ scanf("%d",&ed[i]); vis[ed[i]] = 1; } for(register int i=1;i<=M;++i){ int u = E[i].u;int v = E[i].v; if(vis[u]||vis[v]||(find(u)==find(v)))continue; merge(u,v); count--; } ans[0] = count; for(register int i=1;i<=K;++i){ vis[ed[i]] = 0; count++; for(register int j=head[ed[i]];j;j=G[j].next){ int v = G[j].v; if(!vis[v]&&find(v)!=find(ed[i])){ merge(v,ed[i]); count--; } } ans[i] = count; } for(register int i=K;i>=0;--i){ printf("%d\n",ans[i]); } return 0;}