从m个给定节点计算距离小于k的所有节点的最佳方法

时间:2014-04-23 12:10:19

标签: algorithm graph

给出了大小为n的图表,并给出了其节点的大小m的子集。从子集的所有节点中查找distance <=k的所有节点。

例如。 A-> B-> C-> D-> E是图,subset = {A,C},k = 2.

现在,E与C的距离<= 2,但不是来自A,因此不应计算。

我想到从子集中的每个节点运行广度优先搜索,并考虑相应答案的交集 可以进一步优化吗?

我经历了很多关于SO的帖子,但是他们都指向我不理解的kd-trees,还有其他的方式吗?

3 个答案:

答案 0 :(得分:2)

我可以想到两个非渐近(我相信)的优化:

  1. 如果您使用其中一个子集节点完成BFS,请删除距离为&gt;的所有节点。从它开始
  2. 从距离最大的子集中的两个节点开始,以获得最小的剩余图
  3. 当然,如果k很大(接近n),这没有任何帮助,在这种情况下我不知道。但我很肯定k / d树不适用于一般图表:)

答案 1 :(得分:0)

Nicklas B的优化可以应用于以下两种优化。

优化#1:修改BFS以在运行时而不是在后面执行交集。

BFS和交叉路口似乎是要走的路。但是,BFS正在进行减少工作。特别是,它正在扩展它不需要扩展的节点(在第一个BFS之后)。这可以通过将交叉点方面合并到BFS中来解决。

解决方案似乎是保留两组节点,称之为#34; ToVisit&#34; &#34;访问&#34;而不是标记访问过的节点。

BFS的新规则如下:

  1. BFS仅扩展ToVisit中的节点。然后将它们从ToVisit移动到Visited以防止被扩展两次。
  2. 算法返回Visited set,因为它的结果将丢弃ToVisit中剩余的任何节点。然后将其用作下一个节点的ToVisit集。
  3. 第一个节点使用标准BFS算法,或者ToVisit是所有节点的列表。无论哪种方式,结果都成为第二个节点的第二个ToVisit集。
  4. 如果ToVisit集合平均较小,则效果会更好,这往往是m和k远小于N的情况。

    优化#2:如果有足够的查询,则预先计算距离,以便查询只进行交叉。 虽然,这与第一次优化不兼容。如果对不同的子集和k值有足够数量的查询,那么最好提前找到每对节点之间的距离,代价是O(VE)。

    这种方式只需要进行交叉,即O(V * M * Q),其中Q是查询数,M是查询子集的平均大小,V是节点数。如果预期是O(M * Q)> 0的情况。 O(E),那么这种方法应该少工作。注意两个最远的节点是有用的,因为任何等于或大于等的k将始终返回所有顶点的集合,在这种情况下导致查询成本仅为O(V)。

    然后应以四种形式存储距离数据。

    • 第一个是&#34; kCount [A] [k] =距离A&#34;距离为k或更小的节点数。这提供了Niklas B的替代方案。建议&#34;从距离最大的子集中的两个节点开始,以获得最小的剩余图表&#34;在O(m)>的情况下, O(sqrt(V))因为找到最小值是O(m ^ 2)并且最好避免试图找到起始对的最佳选择并且选择一个好的选择。您可以从子集中的两个节点开始,该数据结构中给定k的值最小。您也可以按此指标对子集中的节点进行排序,并按此顺序执行交叉。

    • 第二个是&#34; kMax [A] = A&#34;的最大k,可以使用散列图/字典来完成。如果k> =该值,那么除非kCount [A] [kMax [A]] <1,否则可以跳过该值。 (顶点数),意味着并非所有节点都可以从A到达。

    • 第三个是&#34; kFrom [A] [k] =节点k与A&#34;的距离,因为k从0到最大距离有效,一个散列图/字典到一个数组/ list可以在这里使用,而不是嵌套的hashmap / dictionary。这样可以节省空间和时间***创建距离为&lt; = k的节点集。

    • 第四个是&#34; dist [A] [B] =从A到B&#34;的距离,这可以使用嵌套的hashmap / dictionary来完成。这允许相当快速地处理交叉检查。

    * 如果空间不是问题,那么这个结构可以存储距离A的所有节点k或更小的距离,但这需要O(V ^ 3)空间,因此需要时间。然而,主要的好处是它还允许存储大于k距离的单独节点列表。这允许算法使用较小的集合,dist&gt; k或dist&lt; = k。在dist&lt; = k的情况下使用交叉点并在dist&lt; = k或交叉点的情况下设置减法,然后在主集具有最小化尺寸的情况下设置减法。

答案 2 :(得分:0)

  1. 添加一个新节点(让我们说s)并将其连接到所有m个给定节点。
  2. 然后,从s中找到距离小于或等于k + 1的所有节点,并从中减去m。 T(n)=O(V+E)