寻找所有生成树的算法可以非常复杂,可以找到与此相关的研究论文。如果要追求效率则需要非常复杂的算法。但是本文介绍的是非常简单暴力搜索的方法。想法很简单:如果一个图有n个点,就在这张图的所有m个边中选出n-1条边,再判断这n-1条边和这n个点组成的是不是连通图,如果是连通图,则这n个点和n-1条边组成了一个生成树。
判断连通图算法
网上有什么矩阵幂和warshell算法,warshell算法好像挺高端的,但是网上搜索的大部分代码有问题(除非使用专业函数),在我们要解决的问题里也不需要复杂,从第一个点开始找连通的点,再依次找连通点的联通点,最后要是找到的点的个数就是图中点的个数,就说明是连通图。
current = zeros(1,size);
current(1) = 1;
%这里的mark标记找到了多少点,要是找到就标记为1
mark = zeros(1,size);
mark(1) = 1;
while sum(current) > 0
next = zeros(1,size);
for j = 1:size
if current(j)>0
for k = 1:size
if k ~= j && graph(j,k) > 0 && mark(k) == 0
mark(k) = 1;
next(k) = 1;
end
end
end
end
current = next;
end
选取n-1条边
涉及到组合数的问题,matlab已经实现好了,用combntns(A,size) 可以实现从A中选取size个元素
完整代码
function trees = spanningTrees2(size, edges)
number = length(edges);
testEdges = zeros(size-1,2);
test = combntns(1:number,size-1);
su = 1;
trees = [];
for i=1:length(test)
for j = 1:size-1
testEdges(j,1) = edges(test(i,j),1);
testEdges(j,2) = edges(test(i,j),2);
end
graph = zeros(size,size);
for k = 1:size-1
graph(testEdges(k,1),testEdges(k,2)) = 1;
graph(testEdges(k,2),testEdges(k,1)) = 1;
end
current = zeros(1,size);
current(1) = 1;
mark = zeros(1,size);
mark(1) = 1;
while sum(current) > 0
next = zeros(1,size);
for j = 1:size
if current(j)>0
for k = 1:size
if k ~= j && graph(j,k) > 0 && mark(k) == 0
mark(k) = 1;
next(k) = 1;
end
end
end
end
current = next;
end
if sum(mark) == size
trees(:,:,su) = graph;
su = su + 1;
end
end
end
输入:
- size:图中点的个数
- edges:若图中有n条边,则edges是n*2的矩阵,矩阵的每一行代表图中的一条边,例如点1和点2有一条边,则edges有一行是(1,2)。
输出:
所有生成树的邻接表,是一个三维矩阵。
该博客介绍了如何在MATLAB中通过简单暴力搜索法找出图中的所有生成树。首先,通过判断连通图算法确保选取的边构成连通图,接着利用组合数原理选取n-1条边。最后,提供了完整的MATLAB代码实现。
1万+

被折叠的 条评论
为什么被折叠?



