题目:
http://www.lydsy.com/JudgeOnline/problem.php?id=1015 倒着做,变成插入点和边维护强连通分量,用并查集。
注意星球编号是从0~n-1
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
using namespace std;
const int MaxM=300500;
const int MaxK=600500;

int n,m,k,a[MaxM][2],b[MaxK],father[MaxK],ans=0;
bool vis[MaxK],v[MaxK];
int head[MaxK],next[2*MaxM],node[2*MaxM],t=0;
int aans[MaxK];

void add(int x,int y)


{
node[t]=y;
next[t]=head[x];
head[x]=t;
t++;
node[t]=x;
next[t]=head[y];
head[y]=t;
t++;
}

int findfather(int x)


{
if (father[x]==x)

{
return x;
}
return father[x]=findfather(father[x]);
}

bool bing(int x,int y)


{
int fx=findfather(x),fy=findfather(y);
if (fx==fy) return 0;
father[fx]=fy;
return 1;
}

void init()


{
memset(next,-1,sizeof(next));
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&m);
for (int i=0;i<n;i++)

{
vis[i]=0;
father[i]=i;
v[i]=0;
}
for (int i=0;i<m;i++)

{
scanf("%d%d",&a[i][0],&a[i][1]);
add(a[i][0],a[i][1]);
}
scanf("%d",&k);
for (int i=0;i<k;i++)

{
scanf("%d",&b[i]);
vis[b[i]]=1;
}
}

void treat()


{

for (int i=0;i<n;i++)

{
if (vis[i]==1) continue;
ans++;
for (int j=head[i];j!=-1;j=next[j])

{
if (vis[node[j]]==0)

{
if (bing(node[j],i)==1)

{
ans--;
}
}
}
}
}

int main()


{
init();
treat();
aans[k]=ans;
for (int i=k-1;i>=0;i--)

{
vis[b[i]]=0;
ans++;
for (int j=head[b[i]];j!=-1;j=next[j])

{
if (vis[node[j]]==0)

{
if (bing(node[j],b[i])==1)

{
ans--;
}
}
}
aans[i]=ans;
}
for (int i=0;i<=k;i++)

{
printf("%d\n",aans[i]);
}
return 0;
}
