【问题标题】:graph - The implementation of updating Minimum Spanning Tree after adding a new edgegraph - 添加新边后更新最小生成树的实现
【发布时间】:2012-05-01 21:35:46
【问题描述】:

这是消费税

假设给定图 G 的最小生成树 T (有 n 个顶点和 m 个边)和一个权重为 w 的新边 e = (u, v) 我们将添加到 G 中。给出一个有效的算法来找到最小值 图 G + e 的生成树。 您的算法应该在 O(n) 中运行 是时候获得全额学分了。

我有这个想法:

In the MST, just find out the path between u and v. Then find the edge (along the path) with maximum weight; if the maximum weight is bigger than w, then remove that edge from the MST and add the new edge to the MST.


棘手的部分是如何在 O(n) 时间内做到这一点,而且我也被卡住了。

问题是如何存储 MST。在普通 Prim 算法中,MST 存储为父数组,即每个元素都是相应顶点的父节点。

那么假设消费税给了我一个指示 MST 的父数组,我怎样才能在 O(n) 中释放上述算法?

首先,如何从父数组中识别 u 和 v 之间的路径?我可以为 u 和 v 设置两个祖先数组,然后检查共同祖先,然后我可以获得路径,尽管是向后的。我觉得这部分,要找到共同的祖先,至少得在O(n^2)内完成吧?

然后,我们有了路径。但是我们仍然需要找到沿路径的每条边的权重。由于我认为该图将使用 Prim 算法的邻接列表,因此我们必须执行 O(m)(m 是边数)来定位边的每个权重。

...

所以我认为不可能在 O(n) 中执行该算法。我错了吗?

【问题讨论】:

    标签: algorithm data-structures graph minimum-spanning-tree


    【解决方案1】:

    你的想法是对的。请注意,找到uv 之间的路径是O(n)。我假设你有一个parent array 来识别 MST。跟踪从uvuroot vertex 的路径(对于最大边缘)应该只需要O(n)。如果您到达root vertex,只需跟踪从vuroot vertex 的路径。

    现在您有了来自u -> u1 ... -> max_path_vert1 -> max_path_vert2 -> ... -> v 的路径,删除边max_path_vert1->max_path_vert2(假设它大于添加的边)并反转u->...->max_path_vert1 的父项并标记parent[u] = v

    编辑:为清楚起见提供更多解释

    请注意,在 MST 中,任何一对顶点之间都只有一条路径。因此,如果您可以从u->yv->y 追踪,那么您最多只能追踪n 顶点。如果您跟踪的顶点数超过了n,则意味着您访问了一个顶点两次,这在 MST 中不会发生。好的,现在希望你确信从 u->yv->y 跟踪是 O(n)。一旦你有了这些路径,你就建立了从u->v 开始的路径。你怎么看?我假设这是一个无向图,因为为有向图查找 MST 本身就是一个不同的概念。对于无向图,当您有来自x->y 的路径时,您就有来自y-x 的路径。所以,u->y->v 存在。您甚至不需要从y->v 追溯,因为v->y 的权重与y->v 的权重相同。从u->yv->y 跟踪时,只需找到权重最大的边即可。

    现在在 O(1) 中寻找边权重;您如何存储当前的重量?邻接表还是邻接矩阵?对于 O(1) 访问,以存储父顶点数组的方式存储它。所以,weight[v] = weight(v, parent[v])。因此,您将拥有 O(1) 访问权限。希望这会有所帮助。

    【讨论】:

    • 如果我为 MST 使用父数组,我不认为跟踪 u 和 v 之间的路径是 O(n)。例如,如果u不是v的祖先,v不是u的祖先,相反,u和v有一个共同的祖先y,你可以从u溯源到y,从v溯源到y,你怎么能从u溯源到v还是在 O(n) 中 v 到 u?
    • 另外,如何从父数组中获得 O(1) 中每条边的权重?
    • @JacksonTale 编辑了我的答案以获取更多详细信息来回答您的问题。希望澄清。
    【解决方案2】:

    嗯 - 你的解决方案是正确的。

    但是关于实现,我不明白为什么要使用 G 而不是 T 来查找 u 和 v 之间的路径。使用 T 中的任何搜索遍历来查找 u 和 v 之间的路径,将为您提供 O(n)。 - 也就是说,您可以假设 v 是根并执行深度优先搜索算法 [在这种情况下,您必须假设 v 的所有邻居都是孩子] - 一旦找到 u,就停止 DFS - 然后,堆栈中的节点对应于 u 和 v 之间的路径。

    之后很容易找到路径中每条边的成本 (O(n)),删除/添加边也很容易。总共 O(n)。

    这有什么帮助吗?

    或者你可能得到 O(n^2) - 根据我的理解 - 因为你在 O(n) 中访问 T 中的顶点 v 的子级 - 在这里,你必须将你的数据结构呈现为映射数组,以便将成本降低到 O(1)。 [例如,{a,b,c,u,w}(顶点)-> {0,1,2,3,4}(顶点索引)。

    【讨论】:

    • 我认为如果将 MST 作为父数组给出,则查找 u 和 v 之间的路径将花费更多时间。
    • 老实说,我真的不知道您所说的父数组是什么意思,但是在算法中,如果您没有合适的数据结构,那么不要期望始终获得良好的性能。
    • 您能否解释一下您的树是如何存储的(详细) - 如果可能的话,我可能会找到确切的存储方式
    猜你喜欢
    • 2012-04-13
    • 1970-01-01
    • 2011-02-25
    • 2015-02-11
    • 1970-01-01
    • 2016-10-16
    • 2021-10-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多