【解题思路】

  引理:Prufer编码

定义:不断删除树中度数为1的最小序号的点,并输出与其相连的节点的序号,直至树中只有两个节点,所得输出序列即为Prufer编码。

性质:任意一棵n节点的树都可以用长为(n-2)的Prufer编码唯一表示;m度的节点在序列中出现次数为m-1。

  所以,我们只要计算合法的Prufer序列即可。

  设没有度数限制的节点共x个,有度数限制的节点集y,cnt=∑(d-1)(d∈y)。记range(n)=[1,n)∩N。

  对于没有度数限制的节点,共A=xn-2-cnt种相对方案;

  对于有度数限制的节点,共B=∏C(cnt-∑(dj-1)(j∈range(i)),di-1)(i∈range(n+1))种相对方案;

  根据乘法原理,ans=A*B*C(n-2,cnt)。时间复杂度O(n)。

【参考代码】

 1 import math
 2  
 3 def Ginput(prompt=""):
 4     try:
 5         return raw_input(prompt)
 6     except:
 7         return input(prompt)
 8  
 9 if __name__=="__main__":
10     n=int(Ginput())
11     cnt=S=0
12     pai=1
13     for i in range(n):
14         d=int(Ginput())
15         if d>-1:
16             cnt+=1
17             S+=d-1
18             pai*=math.factorial(d-1)
19     tmp=n-2-S
20     ans=math.factorial(n-2)/math.factorial(tmp)/pai*(n-cnt)**tmp
21     print(ans)
View Code