Kruskal的算法:当边缘成为强制性时更新MST

时间:2016-05-07 09:43:36

标签: algorithm computer-science graph-algorithm kruskals-algorithm

给出无向图G =(V,E)。首先询问MST的成本是多少。 我可以很容易地找到使用Kruskall算法,如下所示:

G = (V, E)
for each edge (u, v) in E sorted by wight
{
    if(Find(u) != Find(v))
    {
        Add (u, v) to the MST
        Union(u, v); // put u and v in the same set
    }
}

之后,对于初始图中的每个边,询问最小生成树中该边的新MST的成本应该是多少。

如果MST中已存在边缘,则答案保持不变。否则,我可以再次运行Kruskall。伪代码如下:

G = (V, E)
G1 = runKruskall(G)

for each edge (u, v) in E
{
    ClearUnionSets()
    if (u, v) in G1
    {
        print costOf(G1)
    } else {
        Union(u, v)
        G2 = runKruskall(G)
        print costOf(G2)
    }
}

该方法的问题在于总复杂度为:O(E * E)

我的问题是,如果有更好的解决方案来更新MST,如上所述。

我在想的是,当第一次运行Kruskall时,对于每个边缘(u,v),u和v都在同一个集合中,找到已经存在于部分MST中的最大加权边缘具有(u,v)的循环并将该信息存储在M [u] [v]的矩阵M中。这样做,当边缘成为强制性时更新MST的问题将在O(1)中解决。

任何人都可以帮我吗?

1 个答案:

答案 0 :(得分:1)

对于不在MST上的每个边缘u-v,包括边缘的最小生成树是u-v替换MST上从u到v的路径上的最大边缘的那个。

可以如下有效地找到要更换的边缘。首先,将MST置于任意顶点。我们将修改算法以找到两个顶点的lowest common ancestor(LCA),描述为here。除了为每个顶点存储第2个父节点之外,我们还将存储到第2个父节点的路径上的最大边缘。使用这个数组,当我们计算LCA时,我们还将计算到LCA路径上的最大边缘,这使我们在两个顶点之间的路径上获得最大边缘。

预处理包括在O(E log E)中找到MST并在O(N log N)中构建LCA的父表,需要O(N log N)空间。在此之后,找到每个边缘的修改的MST仅需要对LCA进行一次评估,这可以在O(log N)中执行。因此,总复杂度仅为O(E log E)。