题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1015
题目大意:给定一个无向图,求联通块个数,以及k次每次摧毁一个点后的联通块个数
分析:
将边和摧毁的点全记录下来,反着做即可。
注意被摧毁的点不能算作联通块
并查集
代码:
type
node=record
y,next:longint;
end;
var
g:array [1..2000000] of node;
f,a,b,h:array [0..400000] of longint;
mark:array [1..400000] of boolean;
i,j,m,n,x,y,t,tot,tmp,u,v,ans:longint;
procedure addpath(x,y:longint);
begin
inc(tot);
g[tot].y:=y;
g[tot].next:=h[x];
h[x]:=tot;
end;
function get(x:longint):longint;
begin
if x<>f[x] then
f[x]:=get(f[x]);
exit(f[x]);
end;
begin
readln(n,m);
for i:=1 to m do
begin
readln(x,y);
inc(x);
inc(y);
addpath(x,y);
addpath(y,x);
end;
readln(t);
for i:=1 to t do
begin
readln(a[i]);
inc(a[i]);
mark[a[i]]:=true;
end;
for i:=1 to n do
f[i]:=i;
for i:=1 to n do
if not mark[i] then
begin
tmp:=h[i];
while tmp<>0 do
begin
if not mark[g[tmp].y] then
begin
u:=get(i);
v:=get(g[tmp].y);
if u<>v then
f[v]:=u;
end;
tmp:=g[tmp].next;
end;
end;
for i:=1 to n do
if not mark[i] and (get(i)=i) then
inc(ans);
b[t]:=ans;
for i:=t downto 1 do
begin
u:=a[i];
tmp:=h[u];
inc(ans);
while tmp<>0 do
begin
if not mark[g[tmp].y] then
begin
u:=get(u);
v:=get(g[tmp].y);
if u<>v then
begin
dec(ans);
f[v]:=u;
end;
end;
tmp:=g[tmp].next;
end;
b[i-1]:=ans;
mark[a[i]]:=false;
end;
for i:=0 to t do
writeln(b[i]);
end.