枚举和索引所有可能的n个顶点树[关闭]

Posted

技术标签:

【中文标题】枚举和索引所有可能的n个顶点树[关闭]【英文标题】:Enumerating and indexing all possible trees of n vertices [closed] 【发布时间】:2017-03-13 02:34:13 【问题描述】:

我们一直在尝试找到一种方法来枚举和索引所有可能具有 n 个标记顶点的树。根据凯莱定理,应该有 nn-2 棵树来自 n 个标记的顶点。有没有办法在 C/C++ 中索引所有可能的树,以便当用户输入整数/数字时,会实时生成唯一的树?

【问题讨论】:

欢迎来到 Stack Overflow。请花时间阅读The Tour 并参考Help Center 中的材料,您可以在这里问什么以及如何问。 @πάνταῥεῖ 这看起来很有主题。请不要盲目地用模板淹没网站。 @TatsuyukiIshi 这个问题对我来说看起来太宽泛了,不包含任何特定的 c++ 代码(该标签所必需的),没有像 c/c++ 之类的语言等,那又如何? @πάνταῥεῖ 这道题显然有输入输出的要求。算法问题没有代码sn-p是很常见的,因为我们不知道要编写算法。 (不过,最好指出他拥有的树结构。) @TatsuyukiIshi IMO 甚至 algorithm 问题应该表现出一些努力,伪代码尝试或其他什么。该标签不应被滥用为提出gimme teh codez之类的问题。 【参考方案1】:

快速浏览一下Cayley's formula 上的***文章(您提到的 nn-2 公式)将我指向 Prüfer 序列,它是一个长度为 n-2 的序列,由(可能重复的)节点标签组成。很明显有nn-2个这样的序列,每个序列都可以表示为一个n- 2 位基本 n 数字。每个 Prüfer 序列都对应于具有 n 个标记节点的唯一树不太明显,但这一事实足以证明 Cayley 的公式。

关于 Prüfer 序列的 Wikipedia 文章解释了如何转为 a sequence into its corresponding tree;相当于把一个整数变成一棵树。

我还没有尝试过,但看起来很有说服力。

【讨论】:

@istvan:生成下一个 Prüfer 序列很简单,因为它只是一个 n-2 位的 base-n 数,可以简单地在摊销 O(1) 中递增。 (向后扫描,直到找到一个不是 n-1 的数字;将其递增并将以下数字更改为 0。)将新的 Prüfer 序列变成一棵树并非易事,但这并不是那么困难,可以在 O 中完成(n)。 @istvan:现在我看了一下,OP 并不要求生成所有的树;它只是请求一个算法将范围内的索引转换为我的答案提供的相应树(诚然通过引用;也许我应该解决这个问题。) 能否请您详细说明如何在没有随机试验的情况下找到下一个 Prüfer 序列?也许我的误解源于我正在使用二叉树这一事实,它比所有平面树都更具限制性。 @istvan:确实,对于二叉树来说,它更复杂。但 Q 与二叉树无关。这是关于无根标记树,这是凯莱定理适用的集合。对于该集合,任何 n-2 个节点标签序列都是表示唯一树的有效 Prüfer 序列。 我不确定我能否关注你。对于n=5 叶子,共有v=2n-1=9 顶点和C_(n-1)=14 不同的、非同构标记的二叉树。然而,长度为v-2=7 的所有 14 个有效 Prüfer 序列远小于序列元素6, 6, 7, 7, 8, 8, 9 的 630 个排列(假设顶点标记为1..9)。我在这里错过了什么?【参考方案2】:

我不精通 C 或 C++,但我认为我可以提供这样的理论,即枚举每棵树不应该太难。如果我需要澄清任何事情,请发表评论。

考虑二进制。

取一个邻接矩阵。为了描述一个顶点是否连接到另一个顶点,我们使用 1 或 0。因此,要使用邻接矩阵查找所有图,我们将使用 1 和 0 的所有组合填充一个矩阵。唯一的约束是对于树,一个节点不能是它自己的父节点,也不能有多个父节点。三个顶点的例子:

0 1 1  0 1 1  0 0 1
1 0 0  0 0 0  1 0 0
0 0 0  1 0 0  0 1 0 etc.

我们可以做的是将行并排放置,以便二进制序列描述每个矩阵。示例:

0 1 1 1 0 0 0 0 0  0 1 1 0 0 0 1 0 0  0 0 1 1 0 0 0 1 0 etc.

所以给定九位,我们可以用三个顶点来描述所有的图。这将转换为每个数字 1-2^9 的一棵树,减去彼此旋转的数字。

要将数字转换为树,只需将数字转换为二进制,然后将二进制转换为矩阵。要修复自连接,对于在对角线上或越过对角线的每个“1”,将其进一步移动一个。那么:

1 0 0         1 0 1 
0 1 0    ->   0 0 0
0 0 1         0 1 0

【讨论】:

“我不精通C/C++”难怪没有C/C++这样的语言。 @πάνταῥεῖ 哈哈,我已经编辑它“C 或 C++” 但这会产生很多非树,所以你不能真正使用它来找到给定序数的树。如果你使用最后提出的修正,那么你最终会得到数字和树之间的多对一关系。 @rici 更正消除了非树,但在更正之前存在多树问题。每棵树会有一些恒定数量的数字。我会在今天晚些时候解决这个问题。 @J369:您的提议似乎以 n x n 布尔数组开头,其中有 2^( n ^2) 但 Cayley 的公式预测 n ^( n -2)。这两个值没有明显的关系;我很想知道你是如何把那个圆弄成方形的。

以上是关于枚举和索引所有可能的n个顶点树[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

最小生成树

数据结构中关于最小生成树的步骤

最小生成树

树的每对顶点之间的最大流量和

图——最小生成树

图的最小生成树算法?