有一个有向图(可能包含循环),每个节点上都有一个值,我们怎么能得到每个节点的可达值之和。例如,在下图中:
节点1的可达和为:2 + 3 + 4 + 5 + 6 + 7 = 27
节点2的可达和为:4 + 5 + 6 + 7 = 22
.....
我的解决方案:为了获得所有节点的总和,我认为时间复杂度为O(n + m),n是节点数,m代表边数。应该使用DFS,对于每个节点,我们应该递归地使用一个方法来找到它的子节点,并在完成计算时保存子节点的总和,这样以后我们就不需要再次计算它了。需要为每个节点创建一个集合,以避免由循环引起的无限计算。
有用吗?我不认为它足够优雅,特别是必须创建许多套装。有没有更好的解决方案?感谢。
答案 0 :(得分:5)
这可以通过首先找到Strongly Connected Components (SCC)来完成,这可以在O(|V|+|E|)
中完成。然后,为SCC构建一个新图形G'
(每个SCC是图中的一个节点),其中每个节点的值都是该SCC中节点的总和。
形式上,
G' = (V',E')
Where V' = {U1, U2, ..., Uk | U_i is a SCC of the graph G}
E' = {(U_i,U_j) | there is node u_i in U_i and u_j in U_j such that (u_i,u_j) is in E }
然后,此图(G')是DAG,问题变得更简单,似乎是question linked in comments的变体。
针对此问题的DP解决方案(DAG)可以是:
D[i] = value(i) + sum {D[j] | (i,j) is an edge in G' }
这可以在线性时间内计算(在DAG的topological sort之后)。
伪代码:
总时间为O(|V|+|E|)
。
答案 1 :(得分:2)
您可以使用DFS或BFS算法来解决您的问题。
两者都有复杂性O(V + E)
您不必计算所有节点的所有值。你不需要递归。 做这样的事。
通常DFS看起来像这样。
unmark all vertices
choose some starting vertex x
mark x
list L = x
while L nonempty
choose some vertex v from front of list
visit v
for each unmarked neighbor w
mark w
add it to end of list
在你的情况下你必须添加一些行
unmark all vertices
choose some starting vertex x
mark x
list L = x
float sum = 0
while L nonempty
choose some vertex v from front of list
visit v
sum += v->value
for each unmarked neighbor w
mark w
add it to end of list