分析:思路比较明显了,直接并查集,正着做不行倒着呗,直接倒着做,变成一个个加点,这样就和谐很多了。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
typedef long long ll;
const int N=5e5+5;
int n,m;
int head[N],go[N],next[N];
bool vis[N],bz[N];
int tot,d,fa[N],q[N],ans[N],cnt=1;
int find(int x)
{
if (x==fa[x])return fa[x];
else return fa[x]=find(fa[x]);
}
inline void ins(int x,int y)
{
go[++cnt]=y;
next[cnt]=head[x];
head[x]=cnt;
}
inline void add(int x)
{
int i=head[x],p=find(x),q;
while (i)
{
int v=go[i];
if (vis[v])
{
q=find(v);
if (p!=q)
{
fa[q]=p;
tot--;
}
}
i=next[i];
}
}
int main()
{
scanf("%d%d",&n,&m);
fo(i,0,n-1)fa[i]=i;
fo(i,1,m)
{
int x,y;
scanf("%d%d",&x,&y);
ins(x,y);
ins(y,x);
}
scanf("%d",&d);
fo(i,1,d)
{
scanf("%d",&q[i]);
bz[q[i]]=1;
}
fo(i,0,n-1)
{
if (!bz[i])
{
++tot;
add(i);
vis[i]=1;
}
}
ans[d+1]=tot;
fd(i,d,1)
{
tot++;
add(q[i]);
vis[q[i]]=1;
ans[i]=tot;
}
fo(i,1,d+1)printf("%d\n",ans[i]);
return 0;
}