1、tarjan缩点求割边
2、缩点后此时一定形成一棵树,再把割边加回来求缩点后的各个点的度
3、至少在树上添加(leaf+1)/2 条边,就能 使树达到边二连通,leaf的度为1
var
n,m,l,ans,a,b :longint;
time,top,p,q :longint;
vis :array[0..10010] of boolean;
low,dfn,z,belong:array[0..5010] of longint;
indu :array[0..10010] of longint;
last :array[0..5010] of longint;
pre,other :array[0..20010] of longint;
ge :array[0..20010] of boolean;
i :longint;
procedure connect(x,y:longint);
begin
inc(l);
pre[l]:=last[x];
last[x]:=l;
other[l]:=y;
end;
function min(a,b:longint):longint;
begin
if a<b then exit(a) else exit(b);
end;
procedure dfs(x,father:longint);
var
p,q,cur:Longint;
begin
inc(time);
low[x]:=time;
dfn[x]:=time;
vis[x]:=true;
inc(top);
z[top]:=x;
//
q:=last[x];
while (q<>0) do
begin
p:=other[q];
if dfn[p]=0 then
begin
dfs(p,x);
low[x]:=min(low[x],low[p]);
if low[p]>dfn[x] then
begin
ge[q]:=true;
if (q mod 2=0) then ge[q-1]:=true
else ge[q+1]:=true;
end;
end else
if vis[p] and (p<>father) then low[x]:=min(low[x],dfn[p]);//
q:=pre[q];
end;
//
if (dfn[x]=low[x]) then
begin
cur:=-1;
while (cur<>x) do
begin
cur:=z[top];
dec(top);
vis[cur]:=false;
belong[cur]:=x+n;
end;
end;
end;
begin
read(n,m);l:=0;ans:=0;
for i:=1 to m do
begin
read(a,b);
connect(a,b);
connect(b,a);
end;
dfs(1,0);
//
fillchar(vis,sizeof(vis),false);
for i:=1 to n do
begin
q:=last[i];
while (q<>0) do
begin
if ge[q] then inc(indu[belong[i]]);
q:=pre[q];
end;
end;
//
fillchar(vis,sizeof(vis),false);
for i:=1 to n do
if (indu[belong[i]]=1) and not vis[belong[i]] then
begin
inc(ans);vis[belong[i]]:=true;
end;
//
ans:=(ans+1) div 2;
writeln(ans);
end.
——by Eirlys