要求支持图上的动态删点&&维护联通块个数
似乎这个要求4e5个点不太可做。。
正解是离线下来之后倒序用并查集加点
。。。长见识了
#include<bits/stdc++.h>
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<iostream>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<iomanip>
using namespace std;
#define ll long long
#define pb push_back
#define FOR(a) for(int i=1;i<=a;i++)
const int inf=0x3f3f3f3f;
const int maxn=4e5+9;
int fa[maxn];
void init(int n){for(int i=0;i<n;i++)fa[i]=i;}
int find(int x){return fa[x]==x?fa[x]:fa[x]=find(fa[x]);}
void unite(int a,int b){a=find(a);b=find(b);fa[b]=a;}
vector<int>Gf[maxn];
int n,m,k;
int ou[maxn],ov[maxn];
vector<int>rem;
vector<int>ans;
bool vis[maxn];
int main(){
scanf("%d%d",&n,&m);
init(n);
for(int i=1;i<=m;i++){
scanf("%d%d",&ou[i],&ov[i]);
Gf[ou[i]].pb(ov[i]);
Gf[ov[i]].pb(ou[i]);
}
scanf("%d",&k);
for(int i=1,x;i<=k;i++){
scanf("%d",&x);
rem.pb(x);vis[x]=1;
}
reverse(rem.begin(),rem.end());
init(n);
int now=n-k;
for(int i=1;i<=m;i++){
if(!vis[ou[i]] && !vis[ov[i]]){
if(find(ou[i])!=find(ov[i])){
unite(ou[i],ov[i]);
now--;
}
}
}
ans.pb(now); //全部炸毁
for(int i=0;i<rem.size();i++){ //枚举炸毁点rem[i]
now++;
for(int j=0;j<Gf[rem[i]].size();j++){
if(find(rem[i])!=find(Gf[rem[i]][j]) && !vis[Gf[rem[i]][j]]){
now--;
unite(rem[i],Gf[rem[i]][j]);
}
}
ans.pb(now);
vis[rem[i]]=0;
}
for(int i=ans.size()-1;i>=0;i--){printf("%d\n",ans[i]);}
}