(基本上和强连通的tarjan算法一样)
var n,m,i,j,k,l,num,top,tot,co,ii,x,y,u,v,count,ans,cutedge,root:longint;
head,next,vet,low,dfn,color,d:array[0..400005] of longint;
visit,st,cut:array[0..400005] of boolean;
function min(a,b:longint):longint;
begin if a
procedure add(x,y:longint);
begin
inc(tot);
next[tot]:=head[x];head[x]:=tot;
vet[tot]:=y;
inc(tot);
next[tot]:=head[y];head[y]:=tot;
vet[tot]:=x;
end;
procedure tarjan(x,fa:longint);
var i,v,son:longint;
ok:boolean;
begin
inc(num);dfn[x]:=num;low[x]:=num;
son:=0;st[x]:=true;
i:=head[x];ok:=false;
while i<>0 do begin
v:=vet[i];
if (v=fa)and(not ok) then begin //回边的处理
ok:=true;i:=next[i];continue;
end;
if dfn[v]=0 then begin //v易打错成i
inc(son);
tarjan(v,x);//相较于强连通算法,因为是无向图,所以要记录父亲节点
if low[v]>dfn[x] then inc(cutedge); //从v出发不能回到x及x以前,则
if low[v]>=dfn[x] then cut[x]:=true; //从v出发不能回到x以前,则x为割点
low[x]:=min(low[v],low[x]);//容易打错的地方,v,x要特别注意
end
else if st[v] then low[x]:=min(low[x],dfn[v]);
i:=next[i];
end;
if x=root then begin
if son>1 then cut[x]:=true else cut[x]:=false;//根要特判
end;
st[x]:=false;//搜索过后要复原,使下一次能被搜到
end;
begin
readln(n,m);
for i:=1 to m do begin
readln(u,v);
ADD(u,v);
end;
for i:=1 to n do
if dfn[i]=0 then begin root:=i;tarjan(i,0);end;
for i:=1 to n do if cut[i] then inc(count);
writeln(count,' ',cutedge);
end
基本思路:先将双连通分量缩成点,计算度为1的leaf节点数count,ans=(count+1)>>1
var
n,m,i,j,k,l,num,top,tot,co,ii,x,y,u,v,count,ans:
longint
;
head,next,vet,op,low,dfn,color,d,st:
array
[
0..30005
]
of
longint
;
visit:
array
[
0..30005
]
of
boolean
;
function
min(a,b:
longint
):
longint
;
begin
if
a
then
exit(a);exit(b);
end
;
procedure
add(x,y:
longint
);
begin
inc(tot);
next[tot]:=head[x];head[x]:=tot;
vet[tot]:=y;op[tot]:=tot+
1
;
inc(tot);
next[tot]:=head[y];head[y]:=tot;
vet[tot]:=x;op[tot]:=tot-
1
;
end
;
procedure
tarjan(x:
longint
);
var
i,v:
longint
;
begin
inc(num);dfn[x]:=num;low[x]:=num;
inc(top);st[top]:=x;
i:=head[x];
while
i<>
0
do
begin
if
not
visit[op[i]]
then
begin
visit[i]:=
true
;
v:=vet[i];
if
dfn[v]=
0
then
begin
tarjan(v);
low[x]:=min(low[x],low[v]);
end
else
low[x]:=min(low[x],dfn[v]);
end
else
visit[i]:=
true
;
i:=next[i];
end
;
if
dfn[x]=low[x]
then
begin //边双连通
inc(co);
while
st[top]<>x
do
begin
color[st[top]]:=co;
dec(top);
end
;
color[st[top]]:=co;
dec(top);
end
;
end
;
begin
readln(n,m);
for
i:=
1
to
m
do
begin
readln(u,v);
ADD(u,v);
end
;
for
i:=
1
to
n
do
if
dfn[i]=
0
then
tarjan(i);
for
i:=
1
to
n
do
begin
ii:=head[i];
while
ii<>
0
do
begin
v:=vet[ii];
if
color[v]<>color[i]
then
inc(d[color[v]]);
ii:=next[ii];
end
;
end
;
for
i:=
1
to
co
do
if
d[i]=
1
then
inc(count);
ans:=(count+
1
)>>
1
;
writeln
(ans);
end
.