您的位置:首页 > 其它

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

2011-08-09 06:10 232 查看
求割顶

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

求割顶的算法在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]是割点。

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

粗略的解释一下。。

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

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

有一个小小的优化:

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

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

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

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

code:

View Code

var
i,x,y,j,n,m,k,l,e,js,bb:longint;
a:array[1..2000,1..2000]of longint;
b,v,vv,jj:array[1..2000]of integer;
procedure find(x:longint);
var
i,j:longint;
begin
v[x]:=1;
if x=n then begin bb:=1;exit;end;
for i:=1 to jj[x] do
begin
if (v[a[x,i]]=0) then find(a[x,i]);
if bb=1 then begin
inc(js);
b[js]:=a[x,i];
if a[x,i]=n then b[js]:=0;
break;
end;
end;
end;
procedure doing(x:longint);
var
i,j:longint;
begin
v[x]:=1;
for i:=1 to jj[x] do
if (v[a[x,i]]=0) then doing(a[x,i]);
end;
begin
assign(input,'running.in');
reset(input);
assign(output,'running.out');
rewrite(output);
readln(n,e);
for i:=1 to e do
begin
readln(x,y);
inc(jj[x]);a[x,jj[x]]:=y;
inc(jj[y]);a[y,jj[y]]:=x;
end;
find(1);
for i:=1 to js do
if b[i]<>0 then
begin
fillchar(v,sizeof(v),0);
v[b[i]]:=1;
doing(1);
if v
=0 then vv[b[i]]:=1;
end;
m:=0;
for i:=1 to n do if vv[i]=1 then inc(m);
writeln(m);
for i:=1 to n do if vv[i]=1 then write(i,' ');
close(input);
close(output);
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: