繁体   English   中英

秒最小成本生成树

[英]Second min cost spanning tree

我正在编写一个算法来查找第二个最小成本生成树。 我的想法如下:

  1. 使用 kruskals 找到最低的 MST。
  2. 删除 MST 的最低成本边。
  3. 在整个图上再次运行 kruskals。
  4. 返回新的 MST。

我的问题是:这行得通吗? 有没有更好的方法来做到这一点?

您可以在 O(V 2 ) 中完成。 首先使用Prim 算法计算 MST(可以在 O(V 2 ) 中完成)。

计算max[u, v] = the cost of the maximum cost edge on the (unique) path from u to v in the MST 可以在 O(V 2 ) 中完成。

找到一条边(u, v) ,它不是最小化abs(max[u, v] - weight(u, v))的 MST 的一部分。 可以在 O(E) == O(V 2 ) 中完成。

返回MST' = MST - {the edge that has max[u, v] weight} + {(u, v)} ,这将为您提供第二好的 MST。

这是伪代码和更详细解释的链接

考虑这个案例:

------100----
|           |
A--1--B--3--C
      |     |
      |     3
      |     |
      2-----D

MST 由 ABDC(成本 6)组成。 第二个最小成本是 ABCD(成本 7)。 如果删除最低成本边,您将获得 ACBD(成本 105)。

所以你的想法行不通。 不过我也没有更好的主意...

您可以这样做 - 尝试从图中一次删除 MST 的边,然后运行 ​​MST,从中取出最小值。 所以这与你的相似,除了迭代:

  1. 使用 Kruskals 查找 MST。
  2. 对于 MST 中的每条边:
    1. 从图中删除边
    2. 在 MST 上计算 MST'
    3. 跟踪最小的 MST
    4. 将边添加回图形
  3. 返回最小的 MST。

对您的算法稍作修改。

    Use kruskals to find lowest MST.
    for all edges i of MST
        Delete edge i of the MST.
        Run kruskals again on the entire graph.
        loss=cost new edge introduced - cost of edge i
    return MST for which loss is minimum

这类似于拉里的回答。

找到MST后,

对于每个 new_edge = 不是 MST 中的边

  1. 将 new_edge 添加到 MST。
  2. 找出形成的循环。
  3. 找到循环中权重最大的边,它不是您添加的非 MST 边。
  4. 将重量增加记录为 W_Inc = w(new_edge) - w(max_weight_edge_in_cycle)。
  5. 如果 W_Inc < Min_W_Inc_Seen_So_Far 那么
    • Min_W_Inc_Seen_So_Far = W_Inc
    • edge_to_add = new_edge
    • edge_to_remove = max_weight_edge_in_cycle

来自以下链接的解决方案。
http://web.mit.edu/6.263/www/quiz1-f05-sol.pdf

这是一个在 O(n^2) 中计算第二个最小生成树的算法

  1. 首先找出最小生成树(T)。 在不使用堆的情况下需要 O(n^2)。
  2. 对 T 中的每条边 e 重复。=O(n^2)
  3. 假设当前树边是 e。 这个树边会将树分成两棵树,比如 T1 和 T-T1。 e=(u,v)其中 u 在 T1 中,v 在 T-T1 中。 =O(n^2)

    对 T-T1 中的每个顶点 v 重复。 =O(n^2)

    为 T-T1 中的所有 v 选择边e'=(u,v)并且 e' 在 G(原始图)中并且是最小值

  4. 计算新形成的树的权重。 假设W=weight(T)-weight(e)+weight(e')

  5. 选择权重最小的T1

你的方法行不通,因为它可能是 min. MST 中的权重边是一座桥(只有一条边连接图的 2 个部分),因此与一个 MST 相比,从集合中删除这条边将产生 2 个新的 MST。

基于@IVlad的回答

O(V² log V)算法O(V² log V)

  • 使用 Kruskal 算法(或 Prim 算法)找到最小生成树 (MST),保存其总权重,并为 MST 中的每个节点存储其树邻居(即父节点和所有子节点)-> O(V² log V)
  • 计算最小生成树中任意两个顶点之间的最大边权重。 从 MST 中的每个顶点开始,使用先前计算的树节点邻居列表以深度或广度优先搜索遍历整个树,并存储迄今为止在每个访问的新顶点处遇到的最大边权重。 -> O(V²)
  • 求第二个最小生成树及其总权重。 对于不属于原始 MST 的每条边,尝试通过移除两个顶点之间权重最大的树边来断开它连接的两个顶点,然后将它们与当前考虑的顶点重新连接(注意:MST 应恢复为每次迭代后的原始状态)。 总权重可以通过减去删除边的权重和添加的边的权重来计算。 存储获得的总权重的最小值。

为了练习,您可以尝试竞争性编程问题UVa 10600 - ACM Contest and Blackout ,这涉及按照 OP 的要求在加权图中找到第二个最小生成树。 我的实现(在现代 C++ 中)可以在这里找到。

MST 是一棵树,它具有图所有边的最小权重总和。 因此,第二个最小 mst 将具有图中所有边的第二个最小总权重。

让 T -> BEST_MST(对图中的边进行排序,然后使用 kruskal 算法找到 MST)

T ' -> 第二个最佳 MST

假设 T 有 7 条边,现在要找到 T ',我们将一一删除这 7 条边中的一条并找到该边的替代品(该边的成本肯定会大于我们刚刚从 T 中删除的边)。

假设原始图有 15 条边

我们最好的 MST ( T ) 有 7 个边

和第二好的 MST ( T ' ) 也将只有 7 个边

如何找到T'

T 中有 7 条边,现在对于所有这 7 条边,将它们一一删除并找到这些边的替换。

假设 MST ( T ) 中的边 --> { a,b,c,d,e,f,g }

假设我们的答案将是 2nd_BEST_MST 并且最初它具有无限值(我知道这听起来不太好,让我们暂时假设它)。

对于 BEST_MST 中的所有边:

current_edge = 我找到该边的替代品,该边的替代品的权重肯定会超过第 i 条边(7 个边之一)我们将如何使用 Kruskul 算法找到该边的替代品(我们正在寻找再次使用 MST,因此我们将仅使用 kruskal 算法,但这我们不必再次对边进行排序,因为我们在找到 BEST_MST (T) 时已经这样做了。将生成 NEW_MST 2nd_best_MST = min( NEW_MST , 2nd_best_MST )返回 2nd_best_MST 算法

假设原始图有 10 条边,找到 BEST_MST(使用 kruskal 算法)并假设 BEST_MST 只有 6 条边弓,还有 4 条边不在 BEST_MST 中(因为它们的权重值很大,其中一条边会给我们对于 BEST_MST 中不存在的每条边“X”(即左 4 条边),我们的 2nd_Best_MST 将该边添加到 BEST_MST 中,这将创建循环找到循环中权重最大的边“K”(除了 new_ added_edge 'X' ) 暂时删除边 'K' 这将形成一个新的生成树,计算权重差异并将 weight_difference 映射到边 'X' 。对所有这 4 条边重复步骤 4 并将具有最小权重差异的生成树返回到BEST_MST。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM