嘘~ 正在从服务器偷取页面 . . .

洛谷P2290 [HNOI2004]树的计数 题解


洛谷P2290 [HNOI2004]树的计数 题解

题目链接:P2290 [HNOI2004]树的计数

题意

一个有 \(n\) 个节点的树,设它的节点分别为 \(v_1,v_2,\ldots,v_n\),已知第 \(i\) 个节点 \(v_i\) 的度数为 \(d_i\),问满足这样的条件的不同的树有多少棵。

输入格式

输入文件第一行是一个正整数 \(n\) ,表示树有 \(n\) 个结点。第二行有 \(n\) 个数,第 \(i\) 个数表示 \(d_i\),即树的第 \(i\) 个结点的度数。

输出格式

输出满足条件的树有多少棵。

数据范围

\(1\le n\le 150\),保证满足条件的树不超过 \(10^{17}\) 个。

Prüfer 序列简单题。详见浅谈 Prüfer 序列

则对于给定度数 \(d_{1\sim n}\) 的一棵无根树一共有 \(\dbinom{n-2}{d_1,d_2,\cdots,d_k}=\dfrac{(n-2)!}{\prod_{i=1}^n(d_i-1)!}\) 种情况。

本题需要高精度。因此我使用 \(\mathtt{Python}\)

时间复杂度 \(O(n\times c)\)\(c\) 为数字位数产生的常数

代码:

n = int(input())
if n == 1: # 特判n=1的情况
    x = int(input())
    if(x == 0): print(1)
    else: print(0)
    exit()

fac = [0 for i in range(n+5)]; fac[0] = 1 # 预处理阶乘
for i in range(1,n+1): fac[i] = fac[i-1] * i
ans = fac[n-2]; tot=0; s=input().split()
for i in range(n):
    x = int(s[i])
    if(x == 0): print(0); exit() # 图不连通。
    tot += x-1; ans //= fac[x-1]
if(tot == n-2): print(ans)
else: print(0)

参考文献

[1] https://www.luogu.com.cn/blog/TheLostWeak/solution-p2290


文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录