吼啊~
【题目分析】
战争这道考试题说是和这道题差不多,然后就看了一下,维护的信息比考试题更少了。。。。。。orz
跟考试题差不多,这道题也是离线先储存所有摧毁点(很良心的是一次只有一个点qwq),然后在最后的图上dfs一遍,统计出最后的答案,然后往前加点,每次加点如果没有与之前的联通块相连就ans++,否则如果连接了两个不同联通块就ans--,最后正着输出答案即可。
【代码~】
#include<bits/stdc++.h>
using namespace std;
const int MAXN=4e5+10;
const int MAXM=5e5+10;
int n,m,cnt,q,ans[MAXN];
int fa[MAXN];
int head[MAXN];
int nxt[MAXM],to[MAXM];
int insta[MAXN],sta[MAXN],top;
int dfn[MAXN],low[MAXN],belong[MAXN],tot,sum;
int des[MAXN],sx[MAXN],vis[MAXN];
int Read()
{
int i=0,f=1;
char c;
for(c=getchar();(c>'9'||c<'0')&&c!='-';c=getchar());
if(c=='-')
f=-1,c=getchar();
for(;c>='0'&&c<='9';c=getchar())
i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
int find(int x)
{
if(x==fa[x])
return x;
return fa[x]=find(fa[x]);
}
void merge(int x,int y)
{
x=find(x),y=find(y);
fa[y]=x;
}
void add(int x,int y)
{
nxt[cnt]=head[x];
head[x]=cnt;
to[cnt]=y;
cnt++;
}
void dfs(int u,int f)
{
for(int i=head[u];i!=-1;i=nxt[i])
{
int v=to[i];
if(v==f||vis[v]||des[v])
continue;
vis[v]=1;
fa[v]=find(u);
dfs(v,u);
}
}
int main()
{
memset(head,-1,sizeof(head));
n=Read(),m=Read();
for(int i=1;i<=m;++i)
{
int x=Read(),y=Read();
add(x,y);
add(y,x);
}
int q=Read();
for(int i=0;i<q;++i)
{
sx[i]=Read();
des[sx[i]]=1;
}
for(int i=0;i<n;++i)
fa[i]=i;
for(int i=0;i<n;++i)
if(!vis[i]&&!des[i])
dfs(i,-1),ans[q]++;
for(int i=q-1;i>=0;--i)
{
int u=sx[i],flag=0;
ans[i]=ans[i+1];
des[u]=0;
for(int j=head[u];j!=-1;j=nxt[j])
{
int v=to[j];
if(!des[v])
{
int x=find(u),y=find(v);
if(x==y)
continue;
if(x!=u&&x!=y)
{
ans[i]--;
}
merge(v,u);
flag=1;
}
}
if(!flag)
ans[i]++;
}
for(int i=0;i<=q;++i)
cout<<ans[i]<<'\n';
return 0;
}