在距离d处找到顶点

时间:2016-01-21 09:44:19

标签: algorithm graph-theory

我有一个有N个顶点的树。我想设计一种算法来快速回答一些查询。给定顶点V和整数d,我想在距离为d的距离为d的顶点找到顶点。如果在距离d处有多个顶点,则输出任意顶点。我显然知道如何做蛮力。我也试过一些类似于LCA发现算法的想法(计算距离为1,2,4,8 ......的祖先),但没有任何结果。

我会有很多查询,比如10 ^ 6,所以我想在O(1)或O(log N)时间内回答它们

4 个答案:

答案 0 :(得分:1)

这种方法可行

  1. 计算树中最长路径的质心。为此,请使用深度优先搜索来查找顶点x,其中以x为根的树中顶点深度的最大值为最小值
  2. 使用简单的树遍历计算以x为根的树中所有顶点的深度
  3. 按照连接组件的索引对查询进行分组,如果删除了x,则查询将落入其中
  4. 按组件迭代所有查询。说你的查询是(v,d)。如果depth(v)< = d,则可以使用v的第d个祖先作为答案,使用O(log n)中的standard approach。否则,通过在其中一个组件中查找深度d - 深度(v)(例如在O中),检查是否存在路径(v,w)与x和dist(v,w)= d交叉的解顶点w 1)通过哈希)
  5. 这是有效的,因为如果对于具有深度(v)> = d的查询(v,d)存在答案,则由于x的属性,存在从v开始的跨越x的长度d的路径。

    您可以使用单个深度优先搜索来实施步骤1和步骤。

    对于步骤4,您希望保留一个哈希表,该哈希表以您可以删除的方式将深度与顶点相关联,并在O(1)中添加顶点。然后,您可以在按组件工作时以线性时间执行它。

    总运行时间为O((n + q)* log n)。

    这可以通过使用持久二进制搜索树预先计算步骤4中的深度数据结构在线进行,再次在每个查询的O(log n)中。

答案 1 :(得分:0)

为树的每个边添加一个权重,对应于后代的数量。这只能进行一次,并且是O( N

如果您只想在特定距离 d 找到一个顶点,您可以在O( d )步骤中执行此操作,只需将树向上走,最后向下,如一旦你找到一个足够重的分支来进行 d 步骤。

如果您在同一棵树上进行了很多查询,这将表现得非常好。

答案 2 :(得分:0)

为给定节点构建图形/添加链接 您可以存储该顶点的边缘地图,其中距离为关键点,边距为该值。这样您就可以在O(1)

中构建和检索
class Vertex{
  String vertexLabel;
  Map<Integer,List<Edge> edgeMap;
}

答案 3 :(得分:-1)

一旦你的图形运行Floyd-Warshall算法,计算所有对之间的最短路径,然后使用它? 也许只是从V开始的深度优先搜索并且在深度d处停止就足够了,这取决于您打算执行多少查询。