图的连通性问题——无向图相关_求割顶

求割顶

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

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

什么样的点是割顶?

在一棵DFS树中,

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

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

 

割顶判定算法:

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

  Lowlink [u]= Min { pre[u]

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

                     Lowlink [v]   (uv)是树边,udfs树中是v的父亲    }

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

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


其实这个解释并不是特别明晰。。。

粗略的解释一下。。

求法就是枚举每个点,切断,dfs,若不能到达目标节点,

则当前被切断的点是割顶。(注意标记的点,dfs后要还原)

有一个小小的优化:

先从始点dfs一下。则割顶一定在这条路径上,

记录一下访问过的节点,能够减少枚举的点数。

引申的问题:如果有不能连通的情况,也可以从这次dfs中判断出来。


举个例子:有道题是裸求割顶的,看代码。(表示代码写的不好看。。)

code:

View Code
 1   var
2 i,x,y,j,n,m,k,l,e,js,bb:longint;
3 a:array[1..2000,1..2000]of longint;
4 b,v,vv,jj:array[1..2000]of integer;
5 procedure find(x:longint);
6 var
7 i,j:longint;
8 begin
9 v[x]:=1;
10 if x=n then begin bb:=1;exit;end;
11 for i:=1 to jj[x] do
12 begin
13 if (v[a[x,i]]=0) then find(a[x,i]);
14 if bb=1 then begin
15 inc(js);
16 b[js]:=a[x,i];
17 if a[x,i]=n then b[js]:=0;
18 break;
19 end;
20 end;
21 end;
22 procedure doing(x:longint);
23 var
24 i,j:longint;
25 begin
26 v[x]:=1;
27 for i:=1 to jj[x] do
28 if (v[a[x,i]]=0) then doing(a[x,i]);
29 end;
30 begin
31 assign(input,'running.in');
32 reset(input);
33 assign(output,'running.out');
34 rewrite(output);
35 readln(n,e);
36 for i:=1 to e do
37 begin
38 readln(x,y);
39 inc(jj[x]);a[x,jj[x]]:=y;
40 inc(jj[y]);a[y,jj[y]]:=x;
41 end;
42 find(1);
43 for i:=1 to js do
44 if b[i]<>0 then
45 begin
46 fillchar(v,sizeof(v),0);
47 v[b[i]]:=1;
48 doing(1);
49 if v[n]=0 then vv[b[i]]:=1;
50 end;
51 m:=0;
52 for i:=1 to n do if vv[i]=1 then inc(m);
53 writeln(m);
54 for i:=1 to n do if vv[i]=1 then write(i,' ');
55 close(input);
56 close(output);
57 end.

posted on 2011-08-09 06:10  codeway3  阅读(446)  评论(0编辑  收藏  举报

导航