[英]Node at a longest distance from another node in a tree
给定输入树,我们需要回答类型的查询,
a)
给定上述树的节点,该节点是距该节点最远的节点。
b)
从树中移除一组特定的边。
我已经尝试了很长时间但是我能想到的最好的解决方案是,
对于类型的查询a
电话dfs
功能,这将返回最远的节点在O(N)
但我需要做的更好。 对于类型b
的查询,只需更新树[删除边缘,如果存在]。
所以我上面的解决方案大致为O(K*N)
,其中K
是查询数, N
是节点数。
由于你的树是一般树,也就是说,它没有平衡的概念,甚至没有根,你可以做的一次性查询最好的是O(n)
。 但是,我认为你可以设置一次采用O(n)
时间的树,然后让每个后续查询占用恒定时间。
这个想法是找到树的“中间”,它将树分成大致相等大小的树,称任意部分是任意的,例如, 左和右 。 然后,用它们所在的部分标记各自部分中的所有节点,并存储距离中间最远的左节点和右节点。 当您获得节点的查询时,您只需查看节点的标签并在另一侧报告存储的节点。
鉴于评论[和无根据的downvote],似乎解决方案需要更多解释。 首先,给定节点的最远节点通常不是唯一的。 想象一下,例如一个正好有三个节点的路径。 中间节点有两个最远的节点。 其中任何一个都是解决方案。 基于此,我们的想法是在树中找到一个节点,该节点位于树中两个最远节点之间的路径中间(这些节点之间的距离是奇数,可以选择任一侧的节点)使得距离仅相差一个):如果最远的节点是l个节点分开,则中间节点的路径长度为l / 2到两者或路径为l / 2到1和l / 2 + 1到另一个。
使用这个中间节点到树分成两半,随机称为左 , 右半边,能够确定任何给定的节点相距最远的节点,如果每个节点都知道无论是在左或右半边:在最长的路径将通过中间节点进入另一半并从那里到最远离中间的节点。 让我们调用左边部分ll中最长路径的长度和右边部分lr中最长路径的长度。 不失一般性, lr <ll (只需交换周围的名字)。 与中间相距最远的节点称为n1和nr 。 注意,如果从中间节点引出的多个子树被认为是右部分的一部分,只要最长路径之一(或者如果它是唯一的最长路径)在左侧部分中就可以。
当您想要从节点n说明距离最远的节点时,有三种情况需要考虑:
剩下的唯一问题是如何在O(n)
时间内找到中间节点:
1
标记它们并给它们一个距离0
。 这可以在O(n)
时间[和空间]中完成。 作为最后一次传递,找到具有最大距离标签的相邻节点,并考虑从该节点左侧树上挂起的树。 在将节点标记为具有BFS的左节点的同时,跟踪队列中的最后一个节点以找到nl 。 考虑所有其他子树右树,并用BFS标记它们,作为右节点,也找到nr 。
我想,树的预处理可以更优雅地完成,也可能使用少量通道,但我确信上述方法确实有效。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.