http://poj.org/problem?id=1737
http://www.voidcn.com/article/p-txqbeblo-bkm.html
http://www.voidcn.com/article/p-zvbflxxn-uv.html
 
 
An undirected graph is a set V of vertices and a set of E∈{V*V} edges.An undirected graph is connected if and only if for every pair (u,v) of vertices,u is reachable from v.
You are to write a program that tries to calculate the number of different connected undirected graph with n vertices.
For example, there are 4 different connected undirected graphs with 3 vertices.

 
You are to write a program that tries to calculate the number of different connected undirected graph with n vertices.
For example, there are 4 different connected undirected graphs with 3 vertices.
Input
The input contains several test cases. Each test case contains an integer n, denoting the number of vertices. You may assume that 1<=n<=50. The last test case is followed by one zero.
Output
For each test case output the answer on a single line.
Sample Input
1 2 3 4 0
Sample Output
1 1 4 38
给定 ()个点,在平面上固定其位置,求这些点最多能组成多少个不同的无向连通图。
统计连通图的方案数是困难的,但我们可以轻易地计算出用 N 个点组成任意图的方案数:因为 N 个点的无向图最多有  条边,考虑每条边选或不选,则共有 种不同的图。
求出任意图的方案数后,只要再求出非连通图的方案数,就可以得到答案。考虑  个点组成的非连通图中的点 ,它一定处于一个由 ()个点组成的连通分量中,点  确定后,组成这个连通分量还需要  个点,总方案数为 ;每个连通分量都是一个连通图,可以递归来求;考虑完一个连通分量,图的剩余部分(与该连通分量隔离的  个点)是一个任意图,也可以递归来求。
设  个点组成连通图的方案数为 、组成非连通图的方案数为 、组成任意图的方案数为 ,则递归计算  的公式为:
需要使用高精度。
    public static final int N = 55;
    public static void main(String[] args) throws Exception
    {
        BigInteger []h = new BigInteger[N];
        BigInteger []f = new BigInteger[N];
        BigInteger []g = new BigInteger[N];
        BigInteger p2[] = new BigInteger[N*N];
        BigInteger [][]C = new BigInteger[N][N];
        for (int i=0;i<N;i++)
        {
            for (int j=0;j<=i;j++)
            {
                if (i==j || j==0) C[i][j] = valueOf(1);
                else C[i][j] = C[i-1][j-1].add(C[i-1][j]);
            }
        }
        p2[0] = ONE;
        for (int i=1;i<N*N;i++)
            p2[i] = p2[i-1].multiply(valueOf(2));
        for (int i=0;i<N;i++)
            h[i] = p2[i*(i-1)/2];
        f[1] = BigInteger.valueOf(1);
        g[1] = BigInteger.valueOf(0);
        for (int n=2;n<N;n++)
        {
            g[n] = BigInteger.ZERO;
            for (int k = 1;k < n; k++)
            {
                BigInteger t = C[n-1][k-1].multiply(f[k]);
                t = t.multiply(h[n-k]);
                g[n] = g[n].add(t);
                f[n] = h[n].subtract(g[n]);
            }
        }
        Scanner in = new Scanner(System.in);
        while (in.hasNext())
        {
            int n = in.nextInt();
            if (n == 0) break;
            System.out.println(f[n]);
        }
    }
http://www.voidcn.com/article/p-zvbflxxn-uv.html
将总的方案数减掉所有不连通的方案。
总的方案数是2^(C(n,2)),不连通的方案数可以如下考虑:
当和点1连通的点数共有k个时,方案数为C(n-1,k) * F(k+1),其他n-k-1各点间任意连边即可,方案数为2^(C(n-k-1,2)),所以这样的方案数共有C(n-1,k)* F(k+1)* 2^(C(n-k-1,2))种。
因此可以得到递推公式:
F(n)= 2^(C(n,2))-Sum(C(n-1,k)* F(k+1)* 2^(C(n-k-1,2)) | 0<=k < n)
总的方案数是2^(C(n,2)),不连通的方案数可以如下考虑:
当和点1连通的点数共有k个时,方案数为C(n-1,k) * F(k+1),其他n-k-1各点间任意连边即可,方案数为2^(C(n-k-1,2)),所以这样的方案数共有C(n-1,k)* F(k+1)* 2^(C(n-k-1,2))种。
因此可以得到递推公式:
F(n)= 2^(C(n,2))-Sum(C(n-1,k)* F(k+1)* 2^(C(n-k-1,2)) | 0<=k < n)
令f[i]表示i个点能组成多少种无向图
首先易知我们能生成2^(i*(i-1)/2)种图 但是一些是不合法的 我们要将不合法的干掉
枚举1号节点与多少个点连通
设1号节点所在联通块大小为j(1<=j<=i-1)
那么与1相连的其它点有C(i-1,j-1)中选法,1号节点所在联通块有f[j]种连法,不与1号节点相连的点有2^((i-j)*(i-j-1)/2)种连法
故得到递推式f[i]=2^(i*(i-1)/2)-Σ[1<=j<=i-1]C(i-1,j-1)*f[j]*2^((i-j)*(i-j-1)/2)
w = open("out.out", "w")
f = [0] * 60
C = [[0] * 60 for i in range(60)]
for i in range(0,51):
 C[i][0] = 1
 for j in range(1,i+1):
  C[i][j] = C[i-1][j] + C[i-1][j-1]
for i in range(1,51):
 f[i] = 2**(i*(i-1)//2)
 for j in range(1,i):
  f[i] -= C[i-1][j-1] * (2**((i-j)*(i-j-1)/2)) * f[j]
 w.write("\"%d\",\n" %f[i] )
