数树


11

是一个连接,无向图,没有周期。您的任务是计算给定数量的顶点中有多少棵不同的树。

如果两棵树不是同构的,则认为它们是不同的。如果两个图的各自顶点可以以如下方式配对,则两个图是同构的:当且仅当与另一个图中的那些顶点配对的顶点之间存在边时,一个图中的两个顶点之间才存在边。有关更完整的描述,请参见上面的链接。

要查看大小为1到6的所有不同树的外观,请在此处查看

您要输出的序列是OEIS上的A000055

限制:您的解决方案必须在几分钟或更短的时间内才能在输入上运行6。这并不是要消除指数时间算法,而是要消除双指数时间算法,例如对所有边缘集的强行强制。

输入:任何非负整数。

输入可以通过任何标准方式进行,包括STDIN,命令行参数,功能输入等。

输出:顶点数量与输入数量相同的不同树的数量。

输出可以通过任何标准方式进行,包括STDOUT,函数返回等。

示例: 0, 1, 2, 3, 4, 5, 6, 7应返回1, 1, 1, 1, 2, 3, 6, 11

评分:按字节编码高尔夫。愿最短的代码获胜!

禁止出现标准漏洞

Answers:


3

CJam(69字节)

]qi:X,{1e|,:):N{N\f{1$%!*}W$.*:+}%1$W%.*:+N,/+}/W\+_1,*X=\_W%.*:+-Y/z

在线演示

说明

基本思想是实现OEIS中描述的生成功能。输入是一个令人讨厌的特殊情况,但是我做的最终调整最终导致产生1,因此z(对于绝对值)将其整理掉。这是这里最奇怪的把戏。0-1个ž

.*:+重复三遍,如果将其提取为,看起来可以节省一个字节{.*:+}:F~。但是,这与特殊情况中断,因为它根本不执行外部循环。0


我们对A000081使用辅助生成函数,其项具有递归性

a[0] = 0
a[1] = 1
For n >= 1, a[n+1] = (sum_{k=1}^n a[n-k+1] * sum_{d|k} d * a[d]) / n

dķd×一种[d]dk % d == 0 ? d : 0一种.*一种ķ一种ñN\f{1$%!*}W$.*:+

M

一种[ñ+1个]=1个ñķ=1个ñ一种[ñ-ķ+1个]×中号[ķ]

一种中号1个ññ+1个一种

 qi:X,{   ,:):N{N\f{1$%!*}W$.*:+}%1$W%.*:+N,/+}/

辅助生成函数的要点由A000055的公式部分给出:

G.f.: A(x) = 1 + T(x) - T^2(x)/2 + T(x^2)/2,
where T(x) = x + x^2 + 2*x^3 + ... is the g.f. for A000081.

一种

[X=0]+一种[X]+1个2一种[X/2]-一世=0ñ一种[一世]×一种[ñ-一世]

一种[X/2]X1,*X=

0\+一种[0]=0X=0W\+-2一种[X]+一世=0ñ一种[一世]×一种[ñ-一世]2一种[X]

所以我们已经解释了

 qi:X,{   ,:):N{N\f{1$%!*}W$.*:+}%1$W%.*:+N,/+}/W\+_1,*X=\_W%.*:+-Y/

1]ñ=1个

1]qi:X,1>{ ... }/

X=0一种[-1 1]0[X=0]X!+1e|

一种1个ñ=0

]qi:X,{ ... /+}/

显然除以零。但是如果我们尝试

]qi:X,{1e| ... /+}/

然后就可以了。我们得到

             e# Stack: [] 0
1e|          e# Stack: [] 1
,:):N        e# Stack: [] [1]
{            e# We only execute this loop once
  N\f{1$%!*} e#   1 divides 1, so stack: [] [1]
  W$.*       e#   Remember: if the two arrays supplied to the pointwise operation
             e#   are not the same length then the values from the longer one are
             e#   left untouched. Stack: [] [1]
  :+         e#   Fold over a singleton. Stack: [] 1
}%           e# And that was a map, so stack: [] [1]
1$W%.*:+     e# Another [1] [] .*:+, giving the same result: 1
N,/          e# 1 / 1 = 1
+            e# And we append 1 to a giving [1]

恰好产生了我们所需的价值。

X=0-1个[-1]-1个-1个2-1个×-1个=-1个01个-1个1个z


1

Pyth,35个字节

l{m`SmSSMcXdUQk2.pQusm+L,dhHGhHtQ]Y

示范。

该程序可以分为两个部分:首先,我们生成所有可能的树,然后删除重复项。

此代码生成树:usm+L,dhHGhHtQ]Y。树表示为边的串联列表,如下所示:

[0, 1, 0, 2, 2, 3, 1, 4]

每个数字代表一个顶点,每两个数字代表一个边。它是通过在已存在的每个可能顶点和新创建的顶点之间反复添加一条边,并将其添加到上一步中的每个可能的树上而构建的。这会生成所有可能的树,因为所有树都可以通过将一个顶点及其边缘重复添加到现有树中来生成。但是,将创建同构树。

接下来,对于每棵树,我们执行所有可能的重新标记。通过映射所有可能的顶点排列(m ... .pQ),然后使用,将树从标准顺序转换为该顺序来完成XdUQkd是树,k是排列。

然后,用将边缘分成单独的列表,用c ... 2排序每个边缘内的顶点SM,用排序树内边缘S,给出每个树的规范表示。这两个步骤就是代码mSSMcXdUQk2.pQ

现在,我们有了一个列表列表,其中包括每棵树的每种可能的重新标记。我们用排序这些列表S。任何两个同构树必须能够重新标记到树组中。利用这一事实,我们使用将每个列表转换为字符串`,然后使用形成这些列表的集合{,并使用输出其长度l

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.