题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1005
题意:给出一棵树的某些节点的度数d,有些未给。问满足这个条件的树有多少种?
思路:Prufer序列
对于此题,设给定的度数的点有w个,令:$sum=\sum_{i=1}^{w}(d[i]-1)$
那么在最后的n-2个Prufer数列中这sum个是已经确定的,这sum个位置是给出的w个数的排列,排列数量为:$cnt=C_{n-2}^{sum}\frac{sum!}{\prod_{i=1}^{w}(d[i]-1)!}$
那么剩下的n-2-sum个位置上要放剩下的n-w个点,每个位置都有n-w种,所以最后的答案为:$cnt=C_{n-2}^{sum}\frac{sum!}{\prod_{i=1}^{w}(d[i]-1)!}(n-w)^{n-2-sum}$
import java.util.*;
import java.text.*;
import java.math.*;
public class Main{
public static void PR(String s){
System.out.println(s);
}
public static void PR(int x)
{
System.out.println(x);
}
public static void PR(BigInteger x)
{
System.out.println(x);
}
public static void PR(double s)
{
java.text.DecimalFormat d=new java.text.DecimalFormat("#.000000");
System.out.println(d.format(s));
}
static BigInteger p[]=new BigInteger[1005];
static BigInteger ans;
static int d[]=new int[1005];
static int n;
public static void main(String[] args){
Scanner S=new Scanner(System.in);
n=S.nextInt();
int i;
p[0]=BigInteger.ONE;
for(i=1;i<=n;i++) p[i]=p[i-1].multiply(BigInteger.valueOf(i));
int sum=0,w=0,flag=1;
for(i=1;i<=n;i++)
{
d[i]=S.nextInt();
if(d[i]!=-1)
{
sum+=d[i]-1;
w++;
}
if(d[i]==0||d[i]>n-1) flag=0;
}
if(n==1)
{
if(d[1]==0||d[1]==-1) PR(1);
else PR(0);
}
else if(n==2)
{
if((d[1]==-1||d[1]==1)&&(d[2]==-1||d[2]==1)) PR(1);
else PR(0);
}
else if(flag==0) PR(0);
else
{
ans=p[n-2].divide(p[n-2-sum]);
for(i=1;i<=n;i++) if(d[i]!=-1)
{
ans=ans.divide(p[d[i]-1]);
}
for(i=1;i<=n-2-sum;i++) ans=ans.multiply(BigInteger.valueOf(n-w));
PR(ans);
}
}
}