我有一个DAG,我需要能够在一个区域内找到一定长度的所有可能路径。例如,我想找到包含至少3个顶点但不超过7个的所有路径。我的第一个想法是找到一个找到所有路径的算法,然后将它们除去。
有人可以提供建议吗?
答案 0 :(得分:3)
枚举长度为K的所有路径一般都是O(2 ^ K),所以我认为上面的建议不是枚举所有可能的路径都是好的。例如:
假设此图中的所有边都是从左到右(因此这是DAG)。然后从最左边到最右边的节点有2 ^ 3条路径(即长度为6的2 ^ 3条路径),因为对于3个'钻石'中的每一个,你可以选择采用上面或下面的路径(所以我们看看所有三个二元选择的排列)。您可以按照图案(通过镶嵌钻石)扩展图形,对于K钻石,将有2 ^ K路径,长度为2K。
所以你可能只想枚举你必须的路径(特别是如果它们像你的例子那样很短)。
我认为使用广度优先搜索的上述建议可用于枚举所有路径,但对于较大的情况,空间要求为2 ^ K(当查找长度为K或更小的所有路径时);我这样说是因为你必须记住长度为n-1的所有路径才能找到长度为n的所有路径。深度优先搜索(或者更确切地说是它的修改版本)也可以起作用:
DFS(int maxLen, Node node):
list<Node> path
path.add(node)
DFS_Helper(maxLen, path)
DFS_Helper(int maxLen, list<Node> path):
print(path)
if (path.size() >= maxLen)
return
set<Node> targets = graph.getNodesPointedToBy(path.last())
for Node target in targets:
path.append(target)
DFS(maxLen, path)
path.removeLastNode()
空间用法是O(| V |)(V中的任何顶点顶点集合都可以出现在最多一次递归调用的'目标'集合中,因为图形是非循环的)。请注意,这仍然会有O(2 ^ k)运行时(如上所述不可避免),我猜测因为这个提升将不会有一个现成的算法让你这样做(这就是为什么我包括一些伪代码以上)。这不包括下限,但不应该包括在内。
编辑:我最初认为DFS的空间使用是O(K),其中K是最大路径长度。这是不正确的并且低于实际空间使用量,因为我忽略了在每次递归调用DFS_Helper时包含“目标”集所使用的空间。空间使用量仍远低于BFS。