查找不是树的任何可能直径的一部分的边缘

时间:2019-01-04 20:01:15

标签: data-structures tree graph-algorithm

我很好奇是否有一种快速的方法来查找是否存在一个边缘,该边缘不是n元树的任何可能直径的一部分。例如,在下面的树中,A-B边缘将不是任何直径的一部分。

k-ary tree

我尝试列出所有可能的直径,但这会花费很多时间,而且我敢肯定有更快的方法。

1 个答案:

答案 0 :(得分:2)

让我们从一个更简单的问题开始:我们将如何找到树木的任何直径?一种方法是选择一个节点,然后在该节点处植树。然后可以通过以下两种方式之一找到图形的直径:

  1. 直径可能完全包含在这些子树之一中。
  2. 可以通过获取两个子树的根,计算从每个子树根开始的最长路径,然后通过整个树的根将它们连接在一起来找到直径。

因此,假设我们递归地访问每个子树,并从每个子树中获得从该子树的根部开始的最长路径(我们可以通过让每个节点存储其高度来隐式存储此路径)和纯粹地最长路径的长度在该子树中(可能通过用该树中最长路径的长度标记每个子树来隐式存储)。掌握这些信息后,我们可以找到 some 直径,如下所示:直径为

  1. 仅在这些子树之一中的最长路径,或者
  2. 是通过将两个最长的路径从子树的根开始通过根连接而形成的。

所有这些信息都可以使用O(n)辅助存储在时间O(n)中进行计算,因此,如果我们只需要确定直径是多少,就可以很快地完成。

现在,让我们对其进行修改,以实际找到所有可能使用的边缘。我们可以从根节点开始。考虑通过路径(1)和(2)获得的路径的长度。如果路线(1)产生的路径比路线(2)严格更长,我们可以递归地进入包含该长度路径的每个子树,并运行相同的过程来确定可能使用的边。如果路由(2)产生的路径比路由(2)严格更长,则我们将从根到其具有最长路径的每个子代的边标记为从子树根开始使用,如果存在这样的子树,然后我们将绑定到第二长路径的每个子树标记为正在使用。然后,我们递归地下降到那些子树中,始终沿着包含许多可能的最长路径之一的子树向下走路径。

第二个传播步骤花费时间O(n),因为每个节点正好被访问一次,并且完成的工作与子节点的数量成正比。总的来说,这是一个使用O(n)空间的O(n)时间算法。