给内容没有循环的树(例如最小生成树:http://fr.wikipedia.org/wiki/Fichier:Minimum_spanning_tree.svg) 如果用作root用户,如何计算哪个节点最小化树深度?
答案 0 :(得分:11)
所有树都没有循环。根据定义,树是一个无循环的连通图。如果有一个顶点,答案是微不足道的。所以假设至少有两个顶点。
让 u 和 v 为两个顶点,使它们的距离 d ( u , v )是最大的。应该很容易看出,如果沿着最短的 uv 路径选择一个顶点作为根,深度将至少 ceiling ( d ( u , v )/ 2)。还应该注意的是,如果选择一个顶点作为不在该路径上的根,则深度将大于 ceiling ( d ( u , v )/ 2)。
假设我们已选择根 r 作为沿最小 uv 路径的中间顶点,以便 d ( u , r )= 上限( d ( u , v )/ 2)和 d ( r , v )≤上限( d ( u , v )/ 2)。如果有另一个顶点 w ,那么 d ( r , w )> 上限( 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 ),这与 u 和 v相矛盾距离最远。所以现在深度,以 r 为根, ceiling ( d ( u , v) )/ 2)。
所以我们需要找到距离最大的两个顶点。一旦我们这样做,我们可以使用 uv 的最短路径寻找算法,注意长度,并沿着所述路径中途遍历并使用该中间顶点作为根。
我们如何找到这些顶点?选择一个顶点 w 并将其放入队列中。当队列非空时,将队列中下一个顶点的邻居添加到队列的末尾。当队列为空时,请记下最近删除的顶点。这将是你。再次执行该过程,您将 v 。
为什么这样做?上述算法从 w 中找到距离最远的顶点。如果 w 恰好是 u 或 v ,算法会清楚地找到 v 或 u ,分别。因此,假设 w 既不是 u 也不是 v 。如果算法在第一遍中找到了 u 或 v ,那么它将会起作用(因为它会在第二遍中找到另一个),所以假设,通过矛盾的是,在第一次传递之后,它发现 x ,使得它不是树的最大路径的终点。从三角不等式中我们得到 d ( u , v )≤ d ( u , w )+ d ( w , v )和 d (< em> v , x )≤ d ( v , w )+ d ( w , x )。从第一个减去第二个,我们 d ( u , v ) - d ( v < / em>, x )≤ d ( u , w ) - d ( w , x )。然后,我们可以将其重新排列为 d ( u , v )+ d ( w , x )≤ d ( u , w )+ d (< em> v , x )。由于 d ( w , u )≤ d ( w , x )( x 是来自 w 的最大路径的终点; wu 不能超过 wx )和 d ( v , x )&lt; d ( u , v )( x 不是最大路径的结尾),我们可以加强不等于 d ( u , v )+ d ( w , x )&lt; d ( u , v )+ d ( w , x )。但是,这是不可能的,因此 x 必须位于最大路径的末尾。
答案 1 :(得分:6)
在选择直径的中间节点作为根之后,查找树的diameter。为了找到直径运行两个BFS,第一个BFS从随机节点v
开始,从v
找到最远的节点,命名为x
,第二个BFS从x
名称找到最远的节点它y
。现在x
和y
之间的路径是直径。
答案 2 :(得分:0)
我认为以下算法可能有用(我没有验证它),从图表的任何树表示开始。
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