我知道这个特定问题的答案是O(V + E),对于像树一样的图形,它是有意义的,因为每个顶点只被探索过一次。
但是,假设图中有一个循环。
例如,让我们拍摄一个带有四个顶点A-B-C-D的无向图 A连接到B和C,B和C都连接到D.所以总共有四个边。 A-> B,A-> C,B-> D,C-> D,反之亦然。
我们来做DFS(A)。
它将首先探索B和B的邻居D和D的邻居C.之后C将没有任何边缘,因此它将返回D和B然后A。
然后A将遍历其第二个边缘并尝试探索C,因为它已经被探索过,它将不会做任何事情并且DFS将结束。
但是在这里顶点“C”已经被遍历了两次,而不是一次。显然,最坏的情况时间复杂度可以与V成正比。
有什么想法吗?
答案 0 :(得分:3)
如果您没有维护 visited
设置,用于避免重新访问已访问过的节点,则DFS不是O(V+E)
。事实上,它不是完整的算法 - 因此,如果有一个路径,它甚至可能找不到路径,因为它会陷入无限循环。
请注意,对于无限图,如果您要查找从s
到t
的路径,即使维护了访问集,也无法保证完成,因为您可能会遇到无限分支。
如果您有兴趣保持DFS有效空间消耗的优势,同时仍然是完整的 - 您可以使用iterative deepening DFS,但如果您想要发现整个图形,它不会轻易解决问题,而不是指向特定节点的路径。
编辑:设置visited
的DFS伪代码。
DFS(v,visited):
for each u such that (v,u) is an edge:
if (u is not in visited):
visited.add(u)
DFS(u,visited)
当且仅当它尚未被访问时,很容易看到你在顶点上调用递归,因此答案在顶点和边的数量上确实是线性的。
答案 1 :(得分:0)
您可以访问图形的每个顶点和边缘恒定次数,仍然是O(V + E)。另一种看待它的方法是将成本计入边缘,而不是顶点。