N个结点可以构成多少种不同的树

AAA20090987 2009-12-06 11:51:54
RT

其实这是一道ACM的题目来的,
题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=1294
请大家多多指教,谢谢。
...全文
2651 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
alphaxiang 2009-12-09
  • 打赏
  • 举报
回复
Number of rooted trees with n nodes

http://www.research.att.com/~njas/sequences/A000081

0, 1, 1, 2, 4, 9, 20, 48, 115, 286, 719, 1842, 4766, 12486, 32973, 87811, 235381, 634847, 1721159, 4688676, 12826228, 35221832, 97055181, 268282855, 743724984, 2067174645, 5759636510, 16083734329, 45007066269, 126186554308, 354426847597
haijid8858 2009-12-09
  • 打赏
  • 举报
回复
任务为:下载一款名为热血传奇的网络游戏客户端,然后进入秒卡区五湖四海。注(官方下载地址为http://mir2.sdo.com/web/index.html,可以提供游戏帐号和游戏内需要的道具)任务一:让游戏角色可以控制筛子的点数。注(完成软件1万+奖励1万)任务二:白日门刷金砖。注(完成软件1.5万+奖励1.5万)任务三:刷经验升级。注(完成软件2万+奖励2万)任务四:复制装备。注(完成任务3万+奖励3万)任务五:控制武器升级。注(完成任务3万+奖励3万)完成2种任务,奖励反倍:如任务一和任务二都完成奖励为5万。完成3种任务:奖励反3倍。完成4种任务:奖励反4倍。完成5种任务:奖励反5倍!!!!快过年了。。。赚50万盛大的钱就行了!!!有意的继续详谈!!!
AAA20090987 2009-12-09
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 litaoye 的回复:]
看来我的方法是有问题的,还是FancyMouse和lzy18lzy两位同志的思路对头。
最近一段时间虽然回答了不少问题,但同时也给出了很多的错误答案,误导了不少无辜群众,
非常抱歉呀,尤其是这类ACM题,有些看起来差不多,实际上却是通过不了。

[/Quote]

不用介意,大家共同学习,共同进步嘛,呵呵。
大家加油,共勉。
AAA20090987 2009-12-09
  • 打赏
  • 举报
回复
谢谢大家,我完全明白了。
绿色夹克衫 2009-12-08
  • 打赏
  • 举报
回复
看来我的方法是有问题的,还是FancyMouse和lzy18lzy两位同志的思路对头。
最近一段时间虽然回答了不少问题,但同时也给出了很多的错误答案,误导了不少无辜群众,
非常抱歉呀,尤其是这类ACM题,有些看起来差不多,实际上却是通过不了。

[Quote=引用 16 楼 lzy18lzy 的回复:]
写错注释位置:

另附:测试数据(^_^ 可以打表)
1: 1
2: 1
3: 2
4: 4
5: 9
6: 20
7: 48
8: 115
9: 286
[/Quote]
lzy18lzy 2009-12-08
  • 打赏
  • 举报
回复
写错注释位置:


#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char hash[64];
char test[64];
__int64 DP[64];
__int64 temp[64];
int path[64][64];


void dfs1(int a);
void dfs2(int a,int b,int c,int d,int step);

__int64 TC(__int64 a,__int64 b) // ( C(a,b) a个东西任取b个)
{
__int64 i,j,k;
__int64 num = 1;
memset(test,0,sizeof(char)*64);
for(j=1;j <=b;a--,j++)
{
num = num*a;
for(i = 2;i <=b;i++)
{
if(test[i] == 0)
{
k = num/i;
if(num - k*i == 0)
{
test[i] = 1;
num = k;
}
}
}
}
return num;
}

__int64 CC(__int64 a,__int64 b) //b个盘子,a种水果,每个盘有必需有且只有一个水果
{
__int64 i,j,k;
__int64 num = 0;

j = a <b?a:b;
for(i = 1;i <= j; i++)
{
num = num + TC(a,i)*TC(b-1,i-1);
}
return num;
}

void dfs2(int a,int b,int c,int d,int step) //计算组合
{
__int64 count;
if(step == b)
{
path[d][step] = a;
if(DP[a] == 0) dfs1(a);

count = 1;
memset(hash,0,sizeof(char)*64);
for(step = 1;step <=b;step++) hash[path[d][step]]++;
for(step = 1;step <=40; step++)
{
if(hash[step])
{
count*=CC(DP[step],hash[step]);
}
}
temp[d]+=count;
return;
}

for(;c*(b-step) <=a-c;c++)
{
path[d][step] = c;
if(DP[c] == 0) dfs1(c);
dfs2(a-c,b,c,d,step+1);
}
}

void dfs1(int a) //分割组合
{
int i = a-1;

for(;i>=1;i--)
dfs2(a-1,i,1,a,1);

DP[a] = temp[a];
}

int main()
{
int m;

memset(DP,0,sizeof(__int64)*64);
memset(temp,0,sizeof(__int64)*64);

DP[1] = 1;
dfs1(40);

while(scanf("%d",&m)!=EOF)
{
printf("%I64d\n",DP[m]);
}

return 0;
}



另附:测试数据(^_^ 可以打表)
1: 1
2: 1
3: 2
4: 4
5: 9
6: 20
7: 48
8: 115
9: 286
10: 719
11: 1842
12: 4766
13: 12486
14: 32973
15: 87811
16: 235381
17: 634847
18: 1721159
19: 4688676
20: 12826228
21: 35221832
22: 97055181
23: 268282855
24: 743724984
25: 2067174645
26: 5759636510
27: 16083734329
28: 45007066269
29: 126186554308
30: 354426847597
31: 997171512998
32: 2809934352700
33: 7929819784355
34: 22409533673568
35: 63411730258053
36: 179655930440464
37: 509588049810620
38: 1447023384581029
39: 4113254119923150
40: 11703780079612453
lzy18lzy 2009-12-08
  • 打赏
  • 举报
回复
WA了好几次,DP过了,注意精度问题

/*
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

char hash[64];
char test[64];
__int64 DP[64];
__int64 temp[64];
int path[64][64];


void dfs1(int a);
void dfs2(int a,int b,int c,int d,int step);

__int64 TC(__int64 a,__int64 b)//n个盘子,m种水果,每个盘有必需有只有一个水果
{
__int64 i,j,k;
__int64 num = 1;
memset(test,0,sizeof(char)*64);
for(j=1;j<=b;a--,j++)
{
num = num*a;
for(i = 2;i<=b;i++)
{
if(test[i] == 0)
{
k = num/i;
if(num - k*i == 0)
{
test[i] = 1;
num = k;
}
}
}
}
return num;
}

__int64 CC(__int64 a,__int64 b)
{
__int64 i,j,k;
__int64 num = 0;

j = a<b?a:b;
for(i = 1;i <= j; i++)
{
num = num + TC(a,i)*TC(b-1,i-1);
}
return num;
}

void dfs2(int a,int b,int c,int d,int step) //计算组合
{
__int64 count;
if(step == b)
{
path[d][step] = a;
if(DP[a] == 0) dfs1(a);

count = 1;
memset(hash,0,sizeof(char)*64);
for(step = 1;step<=b;step++) hash[path[d][step]]++;
for(step = 1;step<=40; step++)
{
if(hash[step])
{
count*=CC(DP[step],hash[step]);
}
}
temp[d]+=count;
return;
}

for(;c*(b-step)<=a-c;c++)
{
path[d][step] = c;
if(DP[c] == 0) dfs1(c);
dfs2(a-c,b,c,d,step+1);
}
}

void dfs1(int a) //分割组合
{
int i = a-1;

for(;i>=1;i--)
dfs2(a-1,i,1,a,1);

DP[a] = temp[a];
}

int main()
{
int m;

memset(DP,0,sizeof(__int64)*64);
memset(temp,0,sizeof(__int64)*64);

DP[1] = 1;
dfs1(40);

while(scanf("%d",&m)!=EOF)
{
printf("%I64d\n",DP[m]);
}

return 0;
}

*/
FancyMouse 2009-12-07
  • 打赏
  • 举报
回复
f[n]表示n个节点有多少个不同的树
然后枚举n-1的无序拆分,每个拆分对应子树的节点个数(比如6=1+2+3就是说一个子树有1个节点,一个有2个,一个有3个),然后做f[1]*f[2]*f[3]。对于每一个拆分把这个成绩乘起来。
所以转移的复杂度至少是f(n-1)。这里估计有优化余地但偶现在脑子比较钝暂且不去想。当n=40跑不动了再说吧
AAA20090987 2009-12-07
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 fancymouse 的回复:]
dp,状态转移的时候比如dp[n]转移下去会有f(n)个转移,其中f(n)表示n的无序拆分数。

话说f(40)多大?
[/Quote]

能详细说一下吗?
FancyMouse 2009-12-07
  • 打赏
  • 举报
回复
dp,状态转移的时候比如dp[n]转移下去会有f(n)个转移,其中f(n)表示n的无序拆分数。

话说f(40)多大?
wenzheng38 2009-12-07
  • 打赏
  • 举报
回复
这里所谓的不同,是指树的形态不同,还是可以认为如果树的子节点上的值不同就是不同的?
绿色夹克衫 2009-12-07
  • 打赏
  • 举报
回复
f(1)就是1个点时候对应的结果,f(5)就是5个点对应的结果

[Quote=引用 13 楼 leontown 的回复:]
不好意思,
您的f(1),到f(5)是什么意思啊?

引用 11 楼 litaoye 的回复:
排版全乱了,用代码试试!

[/Quote]
LeonTown 2009-12-07
  • 打赏
  • 举报
回复
不好意思,
您的f(1),到f(5)是什么意思啊?

[Quote=引用 11 楼 litaoye 的回复:]
排版全乱了,用代码试试!

C# code
f(1)+ f(4) 构造的

O
O
O
O
O

O
O
O
O O

O
O
O O
O

O
O
OOO

f(2)+ f(3)构造的

O
O O
O
O


O
O O
O O

f(3)+ f(2)构造的

O
O O
O O

O
OOO
O

算f(4)+ f(1)构造的?还是应该算是f(5)独有的1个?
O
OOOO
[/Quote]
绿色夹克衫 2009-12-07
  • 打赏
  • 举报
回复
1 1 2 4 9 21 51 127
算了几个,不知道对不对!
绿色夹克衫 2009-12-07
  • 打赏
  • 举报
回复
排版全乱了,用代码试试!


f(1) + f(4) 构造的

O
O
O
O
O

O
O
O
O O

O
O
O O
O

O
O
OOO

f(2) + f(3)构造的

O
O O
O
O


O
O O
O O

f(3) + f(2)构造的

O
O O
O O

O
OOO
O

算f(4) + f(1)构造的?还是应该算是f(5)独有的1个?
O
OOOO
绿色夹克衫 2009-12-07
  • 打赏
  • 举报
回复
用递推应该可以吧,简单分析了1下5个的情况,恐怕不太细致。

f(1) + f(4) 构造的

O
O
O
O
O

O
O
O
O O

O
O
O O
O

O
O
OOO

f(2) + f(3)构造的

O
O O
O
O


O
O O
O O

f(3) + f(2)构造的

O
O O
O O

O
OOO
O

算f(4) + f(1)构造的?还是应该算是f(5)独有的1个?
O
OOOO

这样的话看起来有点像catalan数,不过要去掉不少同构的。
alphaxiang 2009-12-06
  • 打赏
  • 举报
回复
看了一下原题跟这个不一样,原题中的所有点是没有区别的。而上面的公式中的点是有标号的。得再想想
alphaxiang 2009-12-06
  • 打赏
  • 举报
回复
这个有个公式:n^(n-2)
证明有好几种,我看过Prüfer序列的证明。
LeonTown 2009-12-06
  • 打赏
  • 举报
回复
MARK
从图示上看,似乎可以通过从已知情况开始,尝试高度的递减来寻找,
还要避免重复
bigc2000 2009-12-06
  • 打赏
  • 举报
回复
我说的是二叉树个数,
如果要带标号的,树,二叉树,不带标号的数,二叉树,avl树,rb树的个数

《算法分析导论》那本书上有,也有怎么计算,不过,我是搞不定
加载更多回复(1)

33,008

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧