摘要
在一个无向图中,如果有一个顶点集合,删除这个顶点集合以及这个集合中所有顶点相关联的边以后,图的连通分量增多,就称这个点集为割点集合。
如果某个割点集合只含有一个顶点X(也即{X}是一个割点集合),那么X称为一个割点
(来自百度百科)
算法思想
其中,下述中的k(v)称为顶点v的DFS编码;f(v)称为顶点的父,v称为f(v)的子,且以f(v)为起始点、v为终点的有向边称为父子边。
先给出有关割点的两个定理
1.在深度优先搜索过程中,若e = uv 是父子边,且k(u)>1,l(v) >= k(u),则u是割点。
2.若r是深度优先搜索过程中生成的树的根,则r是图G割点的充分必要条件是至少有两条以r为尾的父子边
那么首先利用深度搜索算法求出k(u)和边的访问顺序矩阵W;然后利用l(v)的定义,求出每个顶点的l(v)值,再根据以上两个定理进行是否割点的判断;最后输出割点。
程序的参数说明
G为图的邻接矩阵
nc表示所求出的割点的集合
MATLAB实现
function nc = ncutf(G)
n = size(G,1);
if n >= 3
a = sum(G);
b = sum(a == 2);
if b == n
fprintf('本图为圈,无割点。');
else
%深度优先搜索
[W,k] = DFS3(G);
nc = isncf(W,k);
n = size(G,1);
for i = 1:n
for j = 1:n
if W(i,j) > 1
if k(i) > k(j)
G(i,j) = 2;
else
G(i,j) = 3;
end
end
end
end
for i = 1:n
f1 = find(G(i,:) == 2);
f2 = find(G(i,:) == 3);
f = union(f1,f2);
l(i) = min([k(f) k(i)]);
end
for i = 1:n
for j = 1:n
if G(i,j) == 3 & k(i) > 1 & l(j) >= k(i)
nc = union(i,nc);
end
end
end
end
else
fprintf('图的顶点小于3,不存在割点。')
end
%在求割点的算法中,对图进行深度搜索
function [W k f] = DFS3(G)
n = size(G,1);
W = G;
v = 1;
k = zeros(1,n);
f = zeros(1,n);
b = sum(sum(W == 1));
c = sum(k == 0);
d = 1;
if b == 0 & c == 0 & v == 1
d = 0;
end
k(1) = 1;
j = 2;
l = 2;
while d
a = find(W(v,:) == 1);
if isempty(a) & f(v) ~= 0
W(v,f(v)) = l;
l = l + 1;
v = f(v);
else
for i = 1:length(a)
if k(a(i)) == 0
k(a(i)) = j;
j = j + 1;
W(v,a(i)) = l;
l = l + 1;
f(a(i)) = v;
v = a(i);
break;
elseif k(a(i)) ~= 0
W(v,a(i)) = l;
l = l + 1;
end
end
end
b = sum(sum(W));
c = sum(k == 0);
if c == 0 & v == 1
d = 0;
end
end
W;
%在求割点的集合的算法中,判断起始点是否是割点
function nc = isncf(W,k)
nc = [];
T = zeros(size(W));
n = size(W,1);
a = find(W ~= 0);
for i = 1:length(a)
d(i) = W(a(i));
if a(i) / n > floor(a(i) / n)
t(i) = floor(a(i) / n) + 1;
else
t(i) = floor(a(i) / n);
end
t1(i) = mod(a(i),n);
if t1(i) == 0
t1(i) = n;
end
end
[~,c] = sort(d);
p = [1];
pc = 0;
for i = 1:length(a)
if k(t1(c(i))) < k(t(c(i)))
p = union(p,t(c(i)));
T(t1(c(i)),t(c(i))) = 3;
end
if pc == 0
tc = isempty(setdiff([1:n],p));
if tc
t0 = sum(T(1,:) == 3);
if t0 >= 2
nc = union(nc,1);
end
break;
end
end
end
测试
测试用例:G =
0 1 0 0
1 0 0 1
0 0 0 1
0 1 1 0
测试结果:nc =
2 4