星球大战
题目链接
题解
正难则反,我们不妨从反面考虑一下。我们可以考虑建,不考虑拆,先把这些点和他有关联的边去掉,再从后往前加点加边就好了,对于一个点,先单独建立一个联通快,再见他和目前已有的节点连边,如果两个没有联通ans--。
code
#include<bits/stdc++.h>
using namespace std;
int pre[400001],x[400001],y[400001],b[400001],f[400001],a[400001],bj[400001];
vector<int> e[400001];
int find(int x){
return pre[x]==x?x:pre[x]=find(pre[x]);
}
void join(int x,int y){
int fx=find(x),fy=find(y);
if(fx!=fy)
pre[fx]=fy;
}
int main(){
int n,m,k;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d",&x[i],&y[i]);
e[x[i]].push_back(y[i]),e[y[i]].push_back(x[i]);
}
for(int i=0;i<n;i++)
pre[i]=i;
scanf("%d",&k);
for(int i=1;i<=k;i++)
scanf("%d",&b[i]),f[b[i]]=1;
for(int i=1;i<=m;i++)
if(!f[x[i]]&&!f[y[i]])
join(x[i],y[i]);
for(int i=0;i<n;i++)
if(!f[i])
bj[find(i)]++;
for(int i=0;i<n;i++)
if(bj[i])
a[k]++;
for(int i=k;i>=1;i--){
int js=a[i];
js++;
for(int j=0;j<e[b[i]].size();j++){
if(f[e[b[i]][j]])
continue;
int fx=find(b[i]),fy=find(e[b[i]][j]);
if(fx!=fy)
js--,pre[fx]=fy;
}
f[b[i]]=0;
a[i-1]=js;
}
for(int i=0;i<=k;i++)
printf("%d\n",a[i]);
}