并查集-洛谷P1197 [JSOI2008]星球大战
https://www.luogu.org/problem/show?pid=1197
感觉并查集要维护删除好像很棘手;
开两个并查集也无法解决问题;
尴尬;
本着zyy大神的不是考试懒得想的理念发了一下题解;
发现只要倒着来就好了;
就是离线做;
感觉横牛逼啊;
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#define Ll long long
using namespace std;
struct dian{
int fa;
}d[400050];
struct cs{
int to,nxt;
}a[400050];
int ans[400050],in[400050],head[400050];
bool b[400050],vi[400050];
int n,m,x,y,z,ll,sum;
void init(int x,int y){
a[++ll].to=y;
a[ll].nxt=head[x];
head[x]=ll;
}
int get(int x){
if(d[x].fa==-1)return x;
return d[x].fa=get(d[x].fa);
}
void merge(int x,int y){
int a=get(x);
int b=get(y);
if(a==b)return ;
if(!vi[a]&&!vi[b])sum++;//减少增加都要判断的
if(vi[a]&&vi[b])sum--;
vi[a]=vi[b]=1;
d[a].fa=b;
}
void Init(int x){
for(int k=head[x];k;k=a[k].nxt)
if(!b[a[k].to])merge(x,a[k].to);
if(!vi[x])sum++,vi[x]=1;//这个特判显然
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)d[i].fa=-1;
for(int i=1;i<=m;i++){
scanf("%d%d",&x,&y);
x++,y++;
init(x,y);
init(y,x);
}
scanf("%d",&m);
for(int i=1;i<=m;i++)scanf("%d",&in[i]),in[i]++,b[in[i]]=1;
for(int i=1;i<=n;i++)if(!b[i])Init(i);
for(int i=m;i;i--){
ans[i]=sum;
Init(in[i]);
b[in[i]]=0;
}printf("%d\n",sum);
for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
}