链接:点击打开链接
题意:求n个点组成的连通图的种数
代码:
package poj1737;
import java.util.*;
import java.math.BigInteger;
public class Main{ //固定一个点,让0~N-2个点与这个点联通,剩下的点任意连
public static void main(String[] args){ //总数是2^C(n,2),也就是完全图所有边数取还是不取
BigInteger f[]=new BigInteger[2505]; //dp[i]为i个点的种数,则
BigInteger dp[]=new BigInteger[55]; //dp[i]=2^C(i,2)-∑(j=1->n-1)(dp[j]*C(i-1,j-1)*2^(C(i-j,2)))
BigInteger c[][]=new BigInteger[55][55];
int n,i,j;
BigInteger sum;
for(i=0;i<=50;i++)
dp[i]=BigInteger.valueOf(0);
f[0]=BigInteger.valueOf(1);
for(i=1;i<=2500;i++) //因为大数没有pow因此先存起来
f[i]=f[i-1].multiply(BigInteger.valueOf(2));
dp[1]=BigInteger.valueOf(1);
for(i=1;i<=50;i++){
for(j=0;j<=i;j++){
if(j==0||j==i)
c[i][j]=BigInteger.valueOf(1);
else
c[i][j]=c[i-1][j].add(c[i-1][j-1]);
}
}
for(i=2;i<=50;i++){
sum=BigInteger.valueOf(0);
for(j=1;j<=i-1;j++)
sum=sum.add(dp[j].multiply(c[i-1][j-1]).multiply(f[(i-j)*(i-j-1)/2]));
dp[i]=f[i*(i-1)/2].subtract(sum);
}
Scanner cin=new Scanner(System.in);
while(cin.hasNext()){
n=cin.nextInt();
if(n==0) break;
System.out.println(dp[n]);
}
}
}