Đề bài: http://vn.spoj.com/problems/GRAPH_/
Thuật toán: Đây là bài tập cơ bản về thuật toán tìm cầu, khớp. Bạn có thể tham khảo thuật toán trong ebook Giải thuật và lập trình của thầy Lê Minh Hoàng.
Code:
uses math;
const
fi='';
fo='';
maxn=10000;
maxm=50000;
oo=trunc(1e9);
var
link,head,ke : array[-maxm..maxm] of longint;
i,j,n,m,kq1,kq2 : longint;
cau,khop : longint;
iscut : array[1..maxn] of boolean;
count : longint;
cha,num,low : array[1..maxn] of longint;
free : array[-maxm..maxm] of boolean;
nchild : array[1..maxn] of longint;
procedure add(i,u,v:longint);
begin
link[i] :=head[u];
head[u] := i;
ke[i]:=v;
end;
procedure enter;
var u,v : longint;
begin
assign(input,fi);reset(input);
readln(n,m);
for i:=1 to m do
begin
read(u,v);
add(i,u,v);
add(-i,v,u);
end;
close(input);
end;
procedure dfs(u:longint);
var i,j,v : longint;
begin
inc(count);
num[u]:=count;
low[u]:=oo;
i := head[u];
while i<>0 do
begin
if free[i] then
begin
v := ke[i];
free[-i] := false;
if cha[v]=0 then
begin
cha[v]:=u;
dfs(v);
low[u] := min(low[v],low[u]);
end
else
begin
low[u] := min(low[u],num[v]);
end;
end;
i := link[i];
end;
end;
procedure process;
var i,u,v : longint;
begin
fillchar(free,sizeof(free),true);
fillchar(cha,sizeof(cha),0);
for i:=1 to n do
if cha[i]=0 then
begin
cha[i] := -1;
dfs(i);
end;
for v:=1 to n do
begin
u:=cha[v];
if (u<>-1) and (low[v]>=num[v]) then
begin
inc(cau);
end;
end;
for v:=1 to n do
if cha[v]<>-1 then
begin
inc(nchild[cha[v]]);
end;
fillchar(iscut,sizeof(iscut),false);
for v:=1 to n do
if cha[v] <> -1 then
begin
u := cha[v];
if low[v]>=num[u] then
iscut[u]:= iscut[u] or (cha[u]<>-1) or (nchild[u]>=2);
end;
for v:=1 to n do
if iscut[v] then inc(khop);
end;
procedure print;
begin
assign(output,fo);rewrite(output);
writeln(khop,' ',cau);
close(output);
end;
begin
enter;
process;
print;
end.
Recent Comments