链接
p r u f e r prufer prufer序列
p r u f e r prufer prufer序列与无根树一一对应,一棵包含 n n n个节点的无根树,对应一个包含 n − 2 n-2 n−2个元素的 p r u f e r prufer prufer序列
求无根树的 p r u f e r prufer prufer序列
重复进行以下操作,直至树中只剩下两个点:
- 找到一个度数为1,且编号最小的点。
- 把这个点的父亲节点加入序列,然后把这个点从树中删除。
求 p r u f e r prufer prufer序列所表示的无根树
我重复进行以下操作,直至点集中只剩下两个点:(初始化所有点都在点集中)
- 取出prufer序列最前面的元素x。
- 取出在点集中的、且当前不在prufer序列中的最小元素y。
- 在x,y之间连接一条边。(注意前面的取出相当于删除)
最后,我们在点集中剩下的两个点中连一条边。
相关结论
- p r u f e r prufer prufer序列与无根树一一对应。
- 度数为 d i d_i di的节点会在prufer序列中出现 d i − 1 d_i−1 di−1次。
- 一个 n n n个节点的完全图的生成树个数为 n n − 2 n^{n−2} nn−2。
- 对于给定度数的一棵无根树共有 ( n − 2 ) ! ∏ i = 1 n ( d i − 1 ) ! \frac{(n−2)!}{\prod^n_{i=1}(d_i−1)!} ∏i=1n(di−1)!(n−2)!种情况。
题解
这题就是固定了某些元素的出现次数,问你一共有多少种序列
很简单的计数题
代码
maxn = 1010
n = int(input())
deg = []
free = 0
for i in range(n):
d = int(input())
if d==-1: free+=1
else: deg.append(d-1)
fact = []
for i in range(maxn):
if i==0: fact.append(1)
else: fact.append(fact[-1]*i)
tot = sum(deg)
ans = fact[tot]
for x in deg: ans //= fact[x]
ans *= fact[n-2]//fact[tot]//fact[n-2-tot]
for i in range(n-2-tot):
ans *= free
print(ans)