尽管这个线程太旧了,但我有另一种方法来查找图G=(V,E)中的最大生成树(MST)。
我们可以应用某种Prim算法来查找MST。为此,我必须定义最大加权边的割属性。
割性质:假设在任何时候,我们都有一个包含在MST中的顶点集S(暂时假设它已经被计算出来了)。现在考虑集合S/V(不在MST中的顶点):
声明:从S到S/V的边中具有最大权重的边将始终存在于每个MST中。
证明:假设在我们将顶点添加到集合S的某一点时,从S到S/V的最大加权边是e =(u,v),其中u在S中,v在S/V中。现在考虑一个不包含e的MST。将边缘e添加到MST中。它将在原始MST中创建一个循环。遍历循环并找到S中的顶点u'和S/V中的顶点v',使得u'是我们进入S/V之后的最后一个顶点,并且v'是从u到v的路径上的循环中的第一个S/V中的顶点。
删除边缘e' =(u',v'),结果图仍然连接,但边缘e的权重大于e' [因为e是此时从S到S/V的最大加权边],因此这导致了MST的权重总和大于原始MST。因此这是一个矛盾。这意味着边缘e必须存在于每个MST中。
查找MST的算法:
从S = {s}开始// s是起始顶点
while S不包含所有顶点
do
{
对于S中的每个顶点s
添加来自S/V的顶点v,使得边缘e =(s,v)的权重最大
}
end while
实现:
我们可以使用Max Heap / Priority Queue来实现,其中键是从S到S/V的边的最大权重,值是顶点本身。将顶点添加到S等于从堆中提取Max,并且在每次Extract_Max更改刚添加的顶点相邻顶点的键。
因此,它需要m Change_Key操作和n Extract_Max操作。
Extract_Min和Change_Key都可以在O(log n)中实现。n是顶点数。
因此,这需要O(m log n)时间。m是图中的边数。