查找DAG所有顶点的可达性计数
我试图找到一个适中的空间要求的快速算法来解决以下问题。
对于DAG的每个顶点, 在DAG的传递闭包中找到其入度和出度的总和。
鉴于此DAG:
我期待以下结果:
Vertex # Reacability Count Reachable Vertices in closure
7 5 (11, 8, 2, 9, 10)
5 4 (11, 2, 9, 10)
3 3 (8, 9, 10)
11 5 (7, 5, 2, 9, 10)
8 3 (7, 3, 9)
2 3 (7, 5, 11)
9 5 (7, 5, 11, 8, 3)
10 4 (7, 5, 11, 3)
在我看来,如果不实际构造传递闭包,这应该是可能的。 我一直无法在网上找到任何可以准确描述这个问题的东西。 我已经对如何做到这一点有了一些想法,但我想看看SO群体可以提出什么。
对于每个节点,使用BFS或DFS来查找不可达性。
为了找到不可达性,在相反的方向再次进行。
时间复杂度:O(MN + N2),空间复杂度:O(M + N)。
OMG是错误的! 抱歉!
我会留下来,直到有一个好的选择。 如果可能的话,CW编辑可以随时讨论并扩展它。
使用动态编程。
for each vertex V
count[V] = UNKNOWN
for each vertex V
getCount(V)
function getCount(V)
if count[V] == UNKNOWN
count[V] = 0
for each edge (V, V2)
count[V] += getCount(V2) + 1
return count[V]
这是带邻接表的O(|V|+|E|)
。 它只计算传递闭包的出度。 要计算入度,请调用getCount
并使其边相反。 要获得总和,请将这两个呼叫的计数相加。
要知道为什么这是O(|V|+|E|)
,考虑这个问题:每个顶点V
将被访问完全1 + in-degree(V)
次:一次直接在V
,一次为每个边(*, V)
。 在后续访问中, getCount(V)
仅返回O(1)
的记忆count[V]
。
另一种看待它的方法是计算每个边沿将被跟随的次数:恰好一次。
对于一个确切的答案,我认为这很难击败KennyTM的算法。 如果你愿意接近一个近似值,那么坦克计数法(http://www.guardian.co.uk/world/2006/jul/20/secondworldwar.tvandradio)可能会有所帮助。
在[0,1)范围内为每个顶点分配一个随机数。 使用线性时间动态程序(如polygenelubricants's)为每个顶点v计算从v到达的最小数目minreach(v)。然后估计从v到达的顶点数为1 / minreach(v)-1。为了获得更好的精度,几次,并在每个顶点取平均值。
链接地址: http://www.djcxy.com/p/45145.html上一篇: Finding the Reachability Count for all vertices of a DAG
下一篇: What are good jQuery plugins to highlight code and XML content?