1015 星球大战
倒序维护并查集,将删点转换成加点,每次操作后并查集个数就是联通块个数。
不知道为什么set在bzoj上跑的贼慢,洛谷和d......j上都能A在bzoj上T了 换成数组就过了
注意:倒序合并的时候合并的是getf(x)而不是fa[x]
因为倒序合并的原因有些路径是没有压缩过的,fa[x]就会出问题(自闭了一个小时)
/**************************************************************
Problem: 1015
User: syh0313
Language: C++
Result: Accepted
Time:1764 ms
Memory:11900 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
using
namespace
std;
const
int
maxn=400010;
int
n,m,topt,st[maxn],nt[maxn],to[maxn],fa[maxn];
int
q[maxn],ans[maxn],num,size;
bool
f[maxn],v[maxn],s[maxn];
void
add(
int
x,
int
y)
{to[++topt]=y; nt[topt]=st[x]; st[x]=topt;}
int
getf(
int
x)
{
if
(fa[x]==x)
return
x;
fa[x]=getf(fa[x]);
return
fa[x];
}
void
comb(
int
x,
int
y)
{
if
(getf(x)==getf(y))
return
;
fa[getf(y)]=getf(x);
return
;
}
void
dfs(
int
x,
int
father)
{
f[x]=1;
if
(getf(x)!=father) comb(x,father);
int
p=st[x];
while
(p)
{
if
(!f[to[p]]) dfs(to[p],father);
p=nt[p];
}
}
int
main()
{
memset
(v,1,
sizeof
v);
scanf
(
"%d%d"
,&n,&m);
for
(
int
i=1;i<=m;i++)
{
int
xx,yy;
scanf
(
"%d%d"
,&xx,&yy);
add(xx,yy); add(yy,xx);
}
for
(
int
i=0;i<n;i++) fa[i]=i;
scanf
(
"%d"
,&num);
for
(
int
i=1;i<=num;i++)
scanf
(
"%d"
,&q[i]),f[q[i]]=1,v[q[i]]=0;
for
(
int
i=0;i<n;i++)
if
(!f[i]) dfs(i,i),s[getf(fa[i])]=1,size++;
ans[num+1]=size;
for
(
int
i=num;i;i--)
{
int
x=q[i];
int
p=st[x]; v[x]=1;
while
(p)
{
if
(!v[to[p]]) {p=nt[p];
continue
;}
int
ffa=getf(to[p]);
if
(s[ffa]) s[ffa]=0,size--;
comb(x,ffa);
p=nt[p];
}
s[getf(fa[x])]=1; size++;
ans[i]=size;
}
for
(
int
i=1;i<=num+1;i++)
printf
(
"%d\n"
,ans[i]);
return
0;
}