【问题标题】:Please suggest some algorithm to find the node in a tree whose distance to its farthest node is minimum among all the nodes请建议一些算法来找到树中所有节点中与其最远节点的距离最小的节点
【发布时间】:2010-02-25 11:14:31
【问题描述】:

请提出一些算法来在一棵树中找到所有节点中与最远节点的距离最小的节点。

它不是图表,也没有加权。

【问题讨论】:

  • 您需要重新表述您的问题。
  • 他觉得这没有道理。他本质上是在寻找图中最“中心”的顶点(最远的节点是所有节点中最小的节点)。
  • 关于添加的“它不是图”:树是图的一种特殊情况,因此图算法应该适用于您的树,即使效率不是最高。
  • 只是一棵通用树或二叉树或其他一些树?
  • 您需要重新审视您对“图表”一词的理解。一棵树就是一张图。

标签: c++ algorithm data-structures


【解决方案1】:

在树T中选择一个任意节点v。 运行 BFS,使 v 作为 T 的根。 BFS 输出从 vT 的所有其他节点的距离。

现在选择一个离 v 最远的节点 u。 以 u 为根再次运行 BFS。 在新的距离输出中,找到距离 u 最远的节点 w

考虑 uw 之间的路径。 这是树中最长的路径T。 路径中间的节点是树T中心

请注意,一棵树中可能存在两个中心。如果是这样,他们就是邻居。

性能:O(n),其中nT的节点数。

证明

声明:离some节点最远的叶子(u)位于最长的路径上.

如果我们证明它,那么该算法是正确的,因为它首先找到 u,并且由于它是最长路径的一端,因此使用 DFS 自己找到这条路径。

声明的证明:让我们使用 retucto ad absurdum。假设 u---r 是树中最长的路径;对于某些节点 vv---uv---r 都不是 v 的最长路径时间>。相反,最长的路径是v---k。我们有两种情况:

a) u---rv--k 有一个公共节点 o。那么 v--o--uv--o--ru---o---k 短。那么 o---ro---k 短。那么 u---o---r 不是图中最长的路径,因为 u---o---k 更长。这与我们的假设相矛盾。

b) u---rv--k 没有公共节点。但是由于图是连通的,每条路径上都有节点o1o2,使得它们之间的路径o1--o2这两条路径上不包含任何其他节点。与假设的矛盾点与 a) 点相同,但用 o1--o2 而不是单纯的 o(实际上是点 a 只是 b 的一个特例,其中 o1=o2)。

这证明了声明,因此证明了算法的正确性。

(这是Pavel Shved写的证明,原作者可能有更短的证明)。

【讨论】:

  • 您能否透露一些您找到最长路径的方法的原因?
【解决方案2】:

去除叶子。如果剩下超过 2 个节点,请重复。剩下的节点(或 2 个节点)将是您要查找的节点。

为什么会这样:

节点位于树中最长路径P 的中间。它们到任何节点的最大距离最多为路径长度的一半(否则它不会是最长的)。 P 上的任何其他节点显然比找到的节点与P 的另一端有更大的距离。任何不在P 上的节点n 将至少有其最远的节点(从nP 上最近的节点的距离,比如c)+(从c 到@ 的另一端的距离987654330@),所以又比算法找到的节点多。

【讨论】:

  • 我不知道什么是根节点所以不知道什么是叶节点。
  • 叶节点只有一条边。
  • 这总是会找到根节点(假设它有超过1条边,否则它会找到根节点上方的最低分支)
  • @jk:据我了解,边缘是无向的,因此没有“根”。这总是在图中找到最长路径的中间。只有一条边的节点是叶子,所以它会在第一次迭代中被删除。
【解决方案3】:

您可以将Johnson's algorithm 用于稀疏图,否则请使用Floyd-Warshall algorithm,因为它实现起来很简单。

基本上你想找到每个节点到每个其他节点的距离,然后只是简单地搜索你想要的属性。

【讨论】:

  • 这些算法对我来说是新的,而且确实看起来比 Djikstra 更简单。
  • 请注意,FW 为 O(n^3),这可能并不理想。
  • 与重复的 Djikstra 相同,适用于此应用程序。
【解决方案4】:

您可以在每个节点上依次使用 Dijkstra 算法 (http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm),以找到从该节点到其他每个节点的所有距离;扫描结果列表以获取到最远节点的距离。一旦你对每个节点都进行了 Dijkstra 扫描,另一次扫描将为你提供最大距离中的最小值。

Dijkstra 通常被认为具有运行时O(v^2),其中 v 是节点数;您将在每个节点上运行一次,这将在幼稚的实现中将时间增加到O(v^3)。您可以通过存储早期节点的 Dijkstra 运行的结果并在以后的运行中将它们用作已知值来获得收益。

【讨论】:

  • Floyd-Warshall 的代码比 Dijkstra 的要简单得多,但是是的,它具有相同的复杂性。
【解决方案5】:

正如其他人在 cmets 中所说: 树是一个图 - 准确地说是一个无向连接的无环图 - 请参阅 "Tree" (Graph theory)

【讨论】:

  • 一棵树不可能是无向的,不是吗?
  • 一棵树有一个隐含的方向。每个节点到根节点(树不是森林)的距离定义明确,并且两个连接的节点到根节点的距离相差 1。到根节点距离较小的节点为父节点;距离较大的节点是孩子。因此,树形图中的这种父子关系是用纯图术语定义的。此外,树是无环图,因此父母和他们的孩子之间没有其他边。因此,连接节点的父子关系充当边的方向。
猜你喜欢
  • 2020-09-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-19
  • 2020-08-02
  • 1970-01-01
  • 2013-06-15
  • 1970-01-01
相关资源
最近更新 更多