poj3177

边双连通有一个非常简单的做法就是先找出所有桥,然后再dfs一次不走桥即可
答案是(叶子节点的个数+1)/2

 1 type node=record
 2        next,po:longint;
 3      end;
 4 
 5 var e:array[0..20010] of node;
 6     p,dfn,low,d,be,fa:array[0..5000] of longint;
 7     hash:array[0..5000,0..5000] of boolean;
 8     b:array[0..20010] of boolean;
 9     len,n,m,x,y,i,ans,t,s,j,h,r:longint;
10 
11 function min(a,b:longint):longint;
12   begin
13     if a>b then exit(b) else exit(a);
14   end;
15 
16 procedure add(x,y:longint);
17   begin
18     hash[x,y]:=true;
19     inc(len);
20     e[len].po:=y;
21     e[len].next:=p[x];
22     p[x]:=len;
23   end;
24 
25 procedure tarjan(x:longint);
26   var i,y:longint;
27   begin
28     inc(h);
29     dfn[x]:=h;
30     low[x]:=h;
31     i:=p[x];
32     while i<>-1 do
33     begin
34       y:=e[i].po;
35       if y<>fa[x] then
36       begin
37         if dfn[y]=0 then
38         begin
39           fa[y]:=x;
40           tarjan(y);
41         end;
42         low[x]:=min(low[x],low[y]);
43         if low[y]>dfn[x] then
44         begin
45           b[i]:=true;
46           b[i xor 1]:=true;
47         end;
48       end;
49       i:=e[i].next;
50     end;
51   end;
52 
53 procedure dfs(x:longint);
54   var i,y:longint;
55   begin
56     be[x]:=s;
57     i:=p[x];
58     while i<>-1 do
59     begin
60       y:=e[i].po;
61       if (be[y]=0) and not b[i] then dfs(y);
62       if b[i] and (be[x]<>be[y]) then inc(d[be[x]]);
63       i:=e[i].next;
64     end;
65   end;
66 
67 begin
68   len:=-1;
69   fillchar(p,sizeof(p),255);
70   readln(n,m);
71   for i:=1 to m do
72   begin
73     readln(x,y);
74     if not hash[x,y] then
75     begin
76       add(x,y);
77       add(y,x);
78     end;
79   end;
80   tarjan(1);
81   for i:=1 to n do
82     if be[i]=0 then
83     begin
84       inc(s);
85       dfs(i);
86     end;
87 
88   for i:=1 to s do
89     if d[i]=1 then inc(ans);
90   writeln((ans+1) shr 1);
91 end.
View Code

 

原文地址:https://www.cnblogs.com/phile/p/4472970.html