procedure2012
It's not worth it to know you're not worth it!

求割顶

  割顶是去掉后让无向图不再连通的点。

  求割顶的算法在DFS遍历的算法上形成。

什么样的点是割顶?

在一棵DFS树中,

1.根root是割顶   -------------  它至少有两个儿子

2.其他点v是割顶 -------------  它有一个儿子u, 从u或者u的后代出发没有指向v祖先(不含v)的B边, 则删除v以后u和v的父亲不连通, 故为割顶。

 

割顶判定算法:

引入lowlink数组为 从当前点以及它的后代所能到达的点的开始访问时间的最小值。

  Lowlink [u]= Min { pre[u]

                     Pre[v]        (u,v)是后向边

                     Lowlink [v]   (u,v)是树边,u在dfs树中是v的父亲    }

–对于DFS树根, 判断度数是否大于1

–对于其他点u, 如果不是根的直接儿子, 且Lowlink[u] >= d[P[u]], 则它的父亲v=P[u]是割点。

代码:

View Code
 1 //by boboo
2 program qiugeding;
3 var
4 tot,i,j,k,n,m,degree:longint;
5 pre,lowlink:array[0..1000]of longint;
6 b:array[0..1000]of boolean;
7 map:array[0..1000,0..1000]of longint;
8 procedure Init;
9 var x,y:longint;
10 begin
11 readln(n,m);
12 for i:=1 to m do
13 begin
14 read(x,y,map[x,y]);
15 map[y,x]:=map[x,y];
16 end;
17 end;
18 function Min(a,b:longint):longint;
19 begin
20 if a<b then exit(a)
21 else exit(b);
22 end;
23 procedure DFS(v:longint);
24 var u:longint;
25 begin
26 inc(tot);
27 pre[v]:=tot;
28 lowlink[v]:=tot;
29 for u:=1 to n do
30 if map[v,u]>0
31 then begin
32 map[v,u]:=-map[v,u];
33 map[u,v]:=-map[u,v];
34 if pre[u]=0 //此时是树边
35 then begin
36 if v=1 then inc(degree); //记录root在DFS树中的度
37 DFS(u); //递归处理
38 lowlink[v]:=Min(lowlink[v],lowlink[u]); //u是v的儿子,更新
39 if lowlink[u]>=pre[v] //第二种情况
40 then b[v]:=true;
41 end
42 else lowlink[v]:=Min(lowlink[v],pre[u]); //反向边的情况
43 end;
44 end;
45 procedure Main;
46 begin
47 degree:=0;
48 DFS(1);
49 if degree>1 then b[1]:=true //第一种情况
50 else b[1]:=false;
51 for i:=1 to n do
52 if b[i] then writeln(i);
53 end;
54 begin
55 assign(input,'gd.in'); reset(input);
56 assign(output,'gd.out'); rewrite(output);
57 Init;
58 Main;
59 close(input); close(output);
60 end.

求图的桥

桥(割边)是去掉后让无向图不再连通的边。

  求割边的算法也在DFS遍历的算法上形成。

  什么样的边是桥(割边)?

边(u,v)为桥当且仅当它不在任何一个简单回路中。

发现树边(u,v)时若发现v和它的后代不存在一条连接u或其祖先的后向边, 则删除(u,v)后u和v不连通, 因此(u,v)为桥。

 

  桥(割边)的判定算法:

发现树边(u, v)时若Lowlink[v]>d[u](注意不能取等号,区别于求割顶), 则(u,v)为桥

实际代码是测试若lowlink[v]=pre[v]则(u,v)是桥

[代码]:

View Code
 1 //by boboo
2 program qiuqiao;
3 var
4 tot,i,j,k,n,m:longint;
5 pre,lowlink:array[0..1000]of longint;
6 b:array[0..1000]of boolean;
7 map:array[0..1000,0..1000]of longint;
8 procedure Init;
9 var x,y:longint;
10 begin
11 readln(n,m);
12 for i:=1 to m do
13 begin
14 read(x,y);
15 map[x,y]:=i;
16 map[y,x]:=map[x,y];
17 end;
18 end;
19 function Min(a,b:longint):longint;
20 begin
21 if a<b then exit(a)
22 else exit(b);
23 end;
24 procedure DFS(v:longint);
25 var u:longint;
26 begin
27 inc(tot);
28 pre[v]:=tot;
29 lowlink[v]:=tot;
30 for u:=1 to n do
31 if map[v,u]>0
32 then begin
33 map[v,u]:=-map[v,u];
34 map[u,v]:=-map[u,v];
35 if pre[u]=0 //此时是树边
36 then begin
37 DFS(u); //递归处理
38 lowlink[v]:=Min(lowlink[v],lowlink[u]); //u是v的儿子,更新
39 if lowlink[u]=pre[u]
40 then b[-map[u,v]]:=true; //标记边的序号
41 end
42 else lowlink[v]:=Min(lowlink[v],pre[u]); //反向边的情况
43 end;
44 end;
45 procedure Main;
46 begin
47 fillchar(b,sizeof(b),false);
48 DFS(1);
49 for i:=1 to m do
50 if b[i] then writeln(i);
51 end;
52 begin
53 assign(input,'qiao.in'); reset(input);
54 assign(output,'qiao.out'); rewrite(output);
55 Init;
56 Main;
57 close(input); close(output);
58 end.

//来自:boboo的《图的连通性总结》




posted on 2011-10-27 11:46  procedure2012  阅读(1766)  评论(1编辑  收藏  举报