【解题思路】
引理: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)