poj 3177(桥)

来源:互联网 发布:xbox手柄mac驱动下载 编辑:程序博客网 时间:2024/05/21 22:33

Description

In order to get from one of the F (1 <=F <= 5,000) grazing fields (which are numbered 1..F) to another field,Bessie and the rest of the herd are forced to cross near the Tree of RottenApples. The cows are now tired of often being forced to take a particular pathand want to build some new paths so that they will always have a choice of atleast two separate routes between any pair of fields. They currently have atleast one route between each pair of fields and want to have at least two. Ofcourse, they can only travel on Official Paths when they move from one field toanother. 

Given a description of the current set of R (F-1 <= R <= 10,000) pathsthat each connect exactly two different fields, determine the minimum number ofnew paths (each of which connects exactly two fields) that must be built sothat there are at least two separate routes between any pair of fields. Routesare considered separate if they use none of the same paths, even if they visitthe same intermediate field along the way. 

There might already be more than one paths between the same pair of fields, andyou may also build a new path that connects the same fields as some other path.

Input

Line 1: Two space-separated integers: F andR 

Lines 2..R+1: Each line contains two space-separated integers which are thefields at the endpoints of some path.

Output

Line 1: A single integer that is the numberof new paths that must be built.

Sample Input

7 7

1 2

2 3

3 4

2 5

4 5

5 6

5 7

Sample Output

2

 

题目大意:

    给一个无向连通图,求要加几条边就可以把图变成双连通图。

分析:

    我们知道,如果缩点后没有点的入度为1,那么它是一个双连通图。

    先跑一波tarjan,用low来把所有双连通分量缩为一点,变成一个新的图,图中的边是桥,然后把入度为1的点找出来,加边数目就是把这些点连起来的数目,即(ans+1)div 2.

 

const

 maxn=6000;

 maxv=20000;

type

 node=record

 y,other,next:longint;

 f:boolean;

end;

 

var

 g:array [1..maxv] of node;

 dfn,low,ls:array [1..maxn] of longint;

 n,p,e,v,m:longint;

 

function find(x,y:longint):boolean;

 vart:longint;

 begin

 t:=ls[x];

 while t>0 do

  begin

   if g[t].y=y then exit(false);

   t:=g[t].next;

  end;

 exit(true);

 end;

 

procedure add(x,y:longint);

 begin

 inc(e);

 g[e].y:=y;

 g[e].other:=e+1;

 g[e].next:=ls[x];

 ls[x]:=e;

 inc(e);

 g[e].y:=x;

 g[e].other:=e-1;

 g[e].next:=ls[y];

 ls[y]:=e;

 end;

 

function min(x,y:longint):longint;

begin

 ifx<y then exit(x)

       else exit(y);

end;

 

procedure dfs(x:longint);

 var

 t:longint;

begin

 inc(p);

 dfn[x]:=p;

 low[x]:=p;

 t:=ls[x];

 while t>0 do

 with g[t] do

  begin

   if not f then

    begin

     f:=true;

     g[other].f:=true;

     if dfn[y]=0 then

      begin

       if x=1 then inc(v);

       dfs(y);

       low[x]:=min(low[x],low[y]);

      end

      else

       low[x]:=min(low[x],dfn[y]);

    end;

   t:=next;

  end;

end;

 

procedure main;

var

 x,y,i,t,ans:longint;

 indegree:array [1..maxn] of longint;

begin

 fillchar(ls,sizeof(ls),0);

 e:=0; p:=0; v:=0;

 fillchar(g,sizeof(g),0);

 fillchar(dfn,sizeof(dfn),0);

 fillchar(low,sizeof(low),0);

 readln(n,m);

  fori:=1 to m do

  begin

   readln(x,y);

   if find(x,y) then add(x,y);

  end;

 dfs(1);

 fillchar(indegree,sizeof(indegree),0);

 fori:=1 to n do

 begin

  t:=ls[i];

  while t>0 do

   begin

    with g[t] do

     begin

       if low[i]<>low[y] then

       begin

        inc(indegree[low[i]]);

        inc(indegree[low[y]]);

       end;

      t:=next;

     end;

   end;

 end;

 ans:=0;

 fori:=1 to n do if indegree[i]=2 then inc(ans); //因为每条边要算两遍

 writeln((ans+1) div 2);

end;

 

begin

 main;

end.

 

0 0
原创粉丝点击