poj3177 tarjan缩点+割边 模板 【pascal】

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值