对于这种连续删边的问题,可以离线,这样就变成了加边,usaco有类似的题。。
码:
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
#define N 400005
int fu[N],c[N],i,n,j,k,m,a,b,f1,f2,ans,daan[N];
bool cx[N],xx[N];
vector<int>v[N];
int find(int o)
{
if(fu[o]!=o)fu[o]=find(fu[o]);
return fu[o];
}
int main()
{
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)fu[i]=i;
for(i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
a++;b++;
v[a].push_back(b);
v[b].push_back(a);
}
scanf("%d",&k);
for(i=1;i<=k;i++)
{
scanf("%d",&c[i]);
c[i]++;
cx[c[i]]=1;
}
for(i=1;i<=n;i++)
{f1=find(i);
if(cx[i]==0)
{
for(j=0;j<v[i].size();j++)
{
int nd=v[i][j];
if(cx[nd])continue;
f2=find(nd);
if(f1==f2)continue;
fu[f2]=f1;
}
}
}
for(i=1;i<=n;i++)
{
if(xx[find(i)]||cx[i])continue;
xx[find(i)]=1;
ans++;
}
for(i=k;i>=1;i--)
{
daan[i]=ans;
f1=find(c[i]);
cx[c[i]]=0;
for(j=0;j<v[c[i]].size();j++)
{
int nd=v[c[i]][j];
if(cx[nd]==1)continue;
f2=find(nd);
if(f1!=f2)
{
ans--;
fu[f2]=f1;
}
}
ans++;
}
printf("%d\n",ans);
for(i=1;i<=k;i++)
{
printf("%d\n",daan[i]);
}
}