【问题标题】:Number of Vertices Within a Distance from Start Vertex距起始顶点一段距离内的顶点数
【发布时间】:2016-03-06 23:25:53
【问题描述】:

我正在为一位法官处理一个问题,该问题询问有关查找距它一定距离内的顶点数。必须对图上的所有顶点执行此操作。完整的问题规范可以看 here.我有一些Python代码解决程序,但是太慢了。

import sys, collections
raw_input = sys.stdin.readline
n, m, k = map(int, raw_input().split())
dict1 = collections.defaultdict(set)
ans = {i:[set([i])for j in xrange(k)]for i in xrange(1, n+1)}

for i in xrange(m):
    x, y = map(int, raw_input().split())
    dict1[x].add(y)
    dict1[y].add(x)

for point in dict1:
    ans[point][0].update(dict1[point])

for i in xrange(1, k):
    for point in dict1:
        for neighbour in dict1[point]:
            ans[point][i].update(ans[neighbour][i-1])

for i in xrange(1, n+1):
    print len(ans[i][-1])

我的代码所做的是最初创建一组点,这些点是每个顶点的直接相邻点(距离为 0 到 1)。之后,它从所有先前找到的邻居的邻居(距离为 2)中为每个顶点创建一组新的邻居。然后它继续这样做,创建一组新的邻居并增加距离,直到达到最终距离。有没有更好的方法来解决这个问题?

【问题讨论】:

    标签: python algorithm graph-theory


    【解决方案1】:

    有很多好的和快速的解决方案。

    其中之一(不是最快,但足够快)是使用 BFS 算法直到距离 K。只需对所有顶点运行 bfs,它不会在距离超过 K 时将邻居添加到队列中。 K 是运动规范中的参数。

    【讨论】:

      【解决方案2】:

      我会使用adjacency matrix 乘法。邻接矩阵是一个布尔方阵n * n,其中n 是顶点数。如果存在从ij 的边,则adjacency_matrix[i][j] 的值等于1,否则等于0。如果我们将邻接矩阵自身相乘,我们得到长度为 2 的路径。如果我们再次这样做,我们得到长度为 3 的路径,依此类推。在你的情况下,K <= 5 所以不会有太多的乘法。您可以为此使用 numpy ,它会非常快。因此,在伪代码中,您的问题的解决方案如下所示:

      adjacency_matrix = build_adjacency_matrix_from_input()
      initial_adjacency_matrix = adjacency_matrix
      result_matrix = adjacency_matrix
      for i = 2 to K:
          adjacency_matrix = adjacency_matrix * initial_adjacency_matrix
          result_matrix = result_matrix + adjacency_matrix
      for each row of result_matrix print how many values higher then 0 are in it    
      

      【讨论】:

      • 邻接矩阵相乘后的值会大于1吗?如果是这样,这些值会发生什么?
      • 在第一个示例中,一些值在相乘后是 2 或 3。这些是答案的一部分吗?
      • 哦,你是对的,对不起。显然,这些是不同路径的数量。在你的情况下,这并不重要,你只需要检查是否有高于零的数字。抱歉我的错误,我将编辑我的答案。
      • 你知道如何快速求矩阵吗?
      • 使用numpy.dot。这可能是最好的方法。
      【解决方案3】:

      你想要长度

      如果使用 BFS: 这相当于从给定的源顶点开始逐级遍历。下面是一个伪代码,可以计算与给定源顶点距离为 K 的所有顶点:

      Start: Let s be your source vertex and K represent max path length required
      
      Create two Queues Q1 and Q2 and insert source vertex s into Q1
      Let queueTobeEmptied = Q1 // represents the queue that is to be emptied
      Let queueTobeFilled = Q2  // represents the queue that is used for inserting new elements discovered
      Let Result be a vector of vertices: initialize it to be empty
      Note: source vertex s is at level 0, push it to Result vector if that is also required
      
      for(current_level=1; current_level<=K; current_level++) {
          while(queueTobeEmptied is not empty) {
              remove the vertex from queueTobeEmptied and call it as u
              for_each adjacent vertex 'v' of u {
                  if v is not already visited {
                      mark v as visited
                      insert v into the queueTobeFilled     
                      push v to Result                       
                  }
              }
          }
          swap the queues now for next iteration of for loop: swap(queueTobeEmptied, queueTobeFilled)
      }
      
      Empty Q1 and Q2
      
      End: Result is the vector that contains all the vertices of length <= K
      

      【讨论】:

        猜你喜欢
        • 2012-10-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-29
        • 1970-01-01
        • 1970-01-01
        • 2015-11-20
        • 2020-04-07
        相关资源
        最近更新 更多