计算每个节点的有向图中特定节点可以到达的节点数

时间:2011-12-17 23:49:06

标签: algorithm graph

在有向图中(假设它有很多周期)我需要计算每个节点特定节点可以达到的节点数。我怎么能用最小的努力做到这一点?我需要使用哪种算法?

注意:我认为这个问题的合理算法应该递归计算这个数字(如果a连接到b,'节点a'的结果取决于'节点b'的结果)。

1 个答案:

答案 0 :(得分:5)

您正在寻找的算法称为Floyd-Warshall algorithm,这是一种非常好用且高效的动态编程算法。它可用于计算图表中每个单独节点可到达的节点集(transitive closure),尽管它更常用于计算从图中每个单独节点到所有其他节点的最短路径。 / p>

(编辑:Floyd-Warshall算法比你需要的更复杂,因为它被Floyd扩展了一点以计算最短路径。你可能会发现this page有用,它只描述了“Warshall”算法的一部分 - 你需要的部分。)

我正好在课堂上研究它并把纸放在我的桌子上。 F-W的传递闭合版本的重现是:

T(i,j,k) = T(i,j,k-1) ∨ (T(i,k,k-1) ∧ T(k,j,k-1))

当且仅当T(a,b,c)为真时,当且仅当存在从a到b的路径时才使用图中的前c个顶点(在运行算法之前必须给它们任意编号)。

直观地说,重复表示如果出现以下情况,则使用前k个顶点存在从i到j的路径:

  • 在i和j之间有一条直接路径,使用第一个k-1顶点,或
  • 在i和k之间有一条路径,在k和j之间有一条路径,使用第一个k-1顶点。

您可以以典型的动态编程方式构建T(i,j,k)的整个三维表,然后沿源节点计算所需的所有TRUE条目(使用max k) ,获取该源节点的传递闭包的大小。

如果您仍然遵循我的不良解释,您可以通过一些技巧使算法非常有效:

  • 事实证明,你的表中不需要k维;你可以一遍又一遍地覆盖同一行值。现在程序看起来像:

    T(i,j) = T(i,j) || (T(i,k) && T(k,j))

  • 如果T(i,k)为0,那么你可以跳过整个事情,因为在那一步没有任何改变。

  • 如果T(i,k)为1,则新值将为T(i,j) || T(k,j)。这可以用很大的块来完成,因为块OR在现代处理器上非常快。

希望有帮助...