【发布时间】:2011-04-17 07:47:17
【问题描述】:
给定一个无向图,我想生成所有大小为 N 的树的子图,其中 size 指的是树中的边数。
我知道其中有很多(至少对于具有恒定连通性的图来说是指数级的)——但这很好,因为我相信节点和边的数量使得这对于至少较小的 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,新的任意选择的根),并重复直到剩余图的大小
我还忘记了每个访问的节点(所有树的某些调用的每个根)都需要标记,并且上面考虑的子节点集应该只是相邻的未标记子节点。我想我们需要考虑不存在未标记子项但深度> 0的情况,这意味着这个“分支”未能达到所需的深度,并且不能形成解决方案集的一部分(因此整个内部循环与该元组可以被中止)。
那么这会奏效吗?有什么重大缺陷吗?有任何更简单/已知/规范的方法吗?
上述算法的一个问题是它不满足内存效率的要求,因为递归将在内存中保存大量的树。
【问题讨论】:
-
您说您不想将所有图形都保存在内存中。但是内存中所有大小为 N 的图呢?
-
只是为了确保您的术语被理解,以下陈述是否正确? 2 个连接的顶点形成大小为 1 的图。连接成三角形的 3 个顶点形成大小为 3 的图,有 3 个大小为 1 的子图,有 3 个大小为 2 的子图。对吧?
-
我也不想在内存中保存所有大小为 N 的图形。由于分支因子(平均节点度)很高,N 大小的图的数量远大于所有小于 N 的大小的图的数量,所以无论如何,这些语句或多或少是等价的。
-
是的,您对子树数量的描述是正确的。后一种情况也有 0 个大小为 3 的子图,因为不允许循环。
-
你是说每个节点只有一个层次的指标?也就是每个节点都知道自己是祖父母却不知道自己的子孙是谁?因此,您是在说“如果 Node 是祖父母,那么后代的整个可能样本空间是多少?”
标签: algorithm language-agnostic graph tree graph-theory