我知道它们很多(对于具有常数连通性的图至少呈指数增长),但这没关系,因为我相信节点和边数使得至少对于小的N值(比如10或更少)它是可处理的。
该算法应该是内存高效的——也就是说,它不应该需要一次性拥有所有图形或某个大的子集,因为即使对于相对较小的图形,这可能会超出可用内存。因此像DFS这样的算法是理想的。
在伪代码中,假设给定起始图graph和所需长度N: 从任意一个节点root作为起点并调用alltrees(graph, N, root)。
alltrees(graph, N, root)
given that node root has degree M, find all M-tuples with integer, non-negative values whose values sum to N (for example, for 3 children and N=2, you have (0,0,2), (0,2,0), (2,0,0), (0,1,1), (1,0,1), (1,1,0), I think)
for each tuple (X1, X2, ... XM) above
create a subgraph "current" initially empty
for each integer Xi in X1...XM (the current tuple)
if Xi is nonzero
add edge i incident on root to the current tree
add alltrees(graph with root removed, N-1, node adjacent to root along edge i)
add the current tree to the set of all trees
return the set of all trees
这仅找到包含所选初始根的树,因此现在删除此节点并调用alltrees(已删除根的图形,N,新选择的任意根),并重复直到剩余图形的大小 < N (因为将不存在所需大小的树)。
我还忘记了每个访问的节点(每个alltrees调用的根)需要被标记,并且上面考虑的子项集应仅为相邻未标记的子项。 我猜我们需要考虑这样一种情况,即没有未标记的子项存在,但深度> 0,这意味着该“分支”未能达到所需深度,并且不能成为解决方案集的一部分(因此与该元组关联的整个内部循环可以中止)。
这会起作用吗? 有什么主要缺陷吗? 有没有更简单/已知/规范的方法来做到这一点?
上述算法的一个问题是它不满足内存有效的要求,因为递归将在内存中保持大量的树集合。