题目链接
先正着跑一遍图,求出连通块个数,再倒着往图中新增节点,判断连通块个数有没有增加,最后正着输出结果
#include<cstdio>
#include<cstring>
#define _rep(i,a,b) for(int i=(a);i<=(b);i++)
#define _for(i,a,b) for(int i=(a);i<(b);i++)
const int N=4e5+10;
int n,m,k,attack[N];
struct node{
int v,nx;
}edge[N];
int head[N],tot,fa[N],cnt,ans[N];
bool vis[N];
inline void addedge(int u,int v)
{
edge[tot].v=v;
edge[tot].nx=head[u];
head[u]=tot++;
}
int findfa(int x){return fa[x]==x?x:fa[x]=findfa(fa[x]);}
int main()
{
//freopen("in.txt","r",stdin);
scanf("%d%d",&n,&m);
memset(head,-1,sizeof(head));
int u,v;
_rep(i,1,m)scanf("%d%d",&u,&v),addedge(u,v),addedge(v,u);
scanf("%d",&k);
_rep(i,1,k)scanf("%d",&attack[i]),vis[attack[i]]=true;
_for(i,0,n)fa[i]=i;
cnt=n-k;
_for(i,0,n)
{
if(vis[i])continue;
for(int j=head[i];~j;j=edge[j].nx)
{
v=edge[j].v;
if(vis[v])continue;
int fu=findfa(i),fv=findfa(v);
if(fu==fv)continue;
fa[fu]=fv;cnt--;
}
}
ans[k+1]=cnt;
for(int i=k;i;i--)
{
u=attack[i];
vis[u]=false;cnt++;
for(int j=head[u];~j;j=edge[j].nx)
{
v=edge[j].v;
if(vis[v])continue;
int fu=findfa(u),fv=findfa(v);
if(fv==fu)continue;
fa[fu]=fv;cnt--;
}
ans[i]=cnt;
}
_rep(i,1,k+1)printf("%d\n",ans[i]);
return 0;
}