【题目描述】
Find the number of connected labeled undirected graphs with n nodes.

找出有标号的 n个点的无向连通图的个数 .(n<=50)
具体参见pku1737。

【题解】
这种题一般来说就是数学推导公式,然后加上高精或者各种快速算法来做。对于一个n个有标号点的图,总共有2^(n*(n-1)/2)种图,所以我们只要减去不连通的图就行了。令f[n]为点数为n时的答案。定点研究,对于标号为1的点,它所在的连通块必定不与至少1个点连通,那么就枚举跟1号点连通的点的个数k(1<=k<=n-1),对于这连通的k-1个点有c(n-1,k-1)种选法(c是组合数),对于剩下的n-k个点,他们之间的每种情况都可以取到,共2^((n-k-1)*(n-k)/2)种情况。那么就有
t+=f[k]*c(n-1,k-1)*2((n-k-1)*(n-k)/2)  (t用于计数)
最后
f[n]=2^(n*(n-1)/2)-t就解决了。
因为最后答案很大,需要用到高精,我开始不想写,HYF神牛当场教我java的biginteger就是高精数,我就乱写了个源代码。


import  java.io. * ;
import  java.math. * ;
import  java.util. * ;

public   class  Main {
    
static  BigInteger two = BigInteger.valueOf( 2 );
    
public   static   void  main(String args[])
    {
        Scanner cin
= new  Scanner(System.in);
        BigInteger to[]
= new  BigInteger[ 52 ];
        BigInteger f[]
= new  BigInteger[ 52 ];
        BigInteger C[][]
= new  BigInteger[ 52 ][ 52 ];
        C[
1 ][ 1 ] = BigInteger.ONE;
        C[
1 ][ 0 ] = BigInteger.ONE;
        
for  ( int  i = 2 ;i <= 50 ;i ++ )
        {
            C[i][
0 ] = BigInteger.valueOf( 1 );
            
for  ( int  j = 1 ;j < i;j ++ )
                C[i][j]
= C[i - 1 ][j - 1 ].add(C[i - 1 ][j]);
            C[i][i]
= BigInteger.ONE;
        }
        
for  ( int  i = 1 ;i <= 50 ;i ++ )
            to[i]
= two.pow(i * (i - 1 ) / 2 );
        f[
1 ] = BigInteger.valueOf( 1 );
        f[
2 ] = BigInteger.valueOf( 1 );
        f[
3 ] = BigInteger.valueOf( 4 );
        
for  ( int  i = 4 ;i <= 50 ;i ++ )
        {
            f[i]
= to[i];
            
for  ( int  j = 1 ;j < i;j ++ )
                f[i]
= f[i].subtract(f[j].multiply(C[i - 1 ][j - 1 ]).multiply(to[i - j]));
        }
        
while  ( true )
        {
            
int  t = cin.nextInt();
            
if  (t == 0 )
                
break ;
            
else
                System.out.println(f[t]);
        }
    }
}