【问题标题】:Finding the root that minimize tree depth找到最小化树深度的根
【发布时间】:2014-10-09 17:27:30
【问题描述】:

给出一个不包含循环的树(例如最小生成树:http://fr.wikipedia.org/wiki/Fichier:Minimum_spanning_tree.svg) 如果作为根节点,如何计算哪个节点的树深度最小?

【问题讨论】:

  • 澄清:你是在问,给定一个全连接的无向无环图,选择距离最远的节点最近的节点吗?

标签: algorithm graph tree


【解决方案1】:

所有的树都不包含循环。根据定义,树是无环的连通图。如果只有一个顶点,答案是微不足道的。所以假设至少有两个顶点。

uv 为两个顶点,使得它们的距离 d (u, v ) 是最大值。应该很容易看出,如果沿着最短 uv 路径选择一个顶点作为根,深度将至少为 ceiling (d em> (u, v) / 2)。还应注意,如果选择一个顶点作为不在该路径上的根,则深度将大于 ceiling (d (u em>, v) / 2).

假设我们选择了根 r 作为沿最小 uv 路径的中间顶点,使得 d (u , r) = 天花板 (d (u, v ) / 2) 和 d (r, v) ≤ 天花板 (d (u, v) / 2)。如果有另一个顶点,w,使得 d (r, w) > ceiling (d (u, v) / 2),我们会有 d ( u, r) d (w, r) 然后,因为只有树中任意两个不同顶点之间的一条路径,我们有 d (u, v) = d ( u, r) + d (r, v) d (u, r) + d (r, w >) = d (u, w),这与 uv 距离最远。所以现在深度,给定 r 作为根,是 ceiling (d (u, v ) / 2).

所以我们需要找到距离最大的两个顶点。一旦我们这样做了,我们可以对 uv 使用最短路径查找算法,记下长度,然后沿着所述路径遍历一半,并使用中间顶点作为根。

我们如何找到这些顶点?选择一个顶点 w 并将其放入队列中。当队列非空时,将队列中下一个顶点的邻居添加到队列的末尾。当队列为空时,记下最近移除的顶点。这将是 u。再次执行该过程,您将拥有 v

为什么会这样?上述算法找到距离 w 最远的顶点。如果 w 恰好是 uv,则算法清楚地找到 vu,分别。所以假设 w 既不是 u 也不是 v。如果算法在第一遍中找到 uv ,它会再次工作(因为它会在第二遍中找到另一个),所以假设,顺便说一句矛盾的是,在第一次通过后它发现 x 使得它不是树的最大路径的末端。从三角不等式我们有 d (u, v) ≤ d (u, w) + d (w, v) 和 d (v, x) ≤ d (v, w) + d (w, x)。从第一个减去第二个我们有 d (u, v) - d (v, x) ≤ d (u, w) - d (w, x)。然后我们可以将其重新排列为 d (u, v) + d (w, x) ≤ d (u, w) + d (vx)。由于 d (w, u) ≤ d (w, x) (x 是距离 w 的最大路径的终点;wu 不能超过 wx ) 和 d (v, x) d (u, v) (x 不是最大路径的终点),我们可以加强不等式到 d (u, v) + d (w, x) d ( u, v) + d (w, x)。但是,这是不可能的,因此 x 必须位于最大路径的末尾。

【讨论】:

  • 谢谢!没有其他方法?
  • 我的算法/方法和 Saeed 的完全一样。我只是给出了解释/证明,以便您阅读并知道我的答案是正确的。我可以尝试考虑另一种算法/方法。这个有什么问题?
  • 这个没问题,它工作得很好,但我想知道是否有其他方法可以做到这一点(只是出于好奇)
【解决方案2】:

找到树的diameter,然后选择直径的中间节点作为根。为了找到直径运行两个 BFS,第一个 BFS 从随机节点 v 开始,并找到距离 v 最远的节点,命名为 x,第二个 BFS 找到距离 x 最远的节点,命名为 y。现在xy 之间的路径是直径。

【讨论】:

  • @nax,哪个部分的代码,如果你的树有一个好的数据结构,你可以简单地使用任何可用的 web 上的示例 BFS 代码。
  • 对不起我的英语,我的意思是参考而不是来源
  • @nax,我的英文并不比你好,但你想参考哪一部分?你在找证据吗(不难,最好自己试试)。但这是一种民间传说,众所周知的问题和解决方案。
  • 是的,我正在寻找证据。
【解决方案3】:

我认为以下算法可能有效(我没有验证它),从您的图形的任何树表示开始。

S = set of all leaves of the tree
foreach node in S: mark(node)
repeat:
  # at each iteration, S is the set of all nodes at
  # a given min distance to a leave
  # initially this distance is 0, then 1, etc.
  S' = empty set
  foreach node in S:
    parent = parent(node)
    if !marked(parent): S' += parent; mark(parent)
  if S' is empty then S contains all innermost nodes, we are done
  S = S' and continue

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-28
    • 2013-02-07
    • 2017-07-16
    • 2014-08-07
    • 2015-08-14
    • 2014-12-04
    • 2021-07-30
    • 1970-01-01
    相关资源
    最近更新 更多