带标号的连通图计数

给n个带有标号的点,求其连通图的种数,设f(i)为答案,g(i)为不连通的图种数,h(i)表示图的总数

有f(i)+g(i) = h(i) = 2^(n*(n-1)/2)

考虑标号为1的节点所在的连通分量,则可以按照其所在连通分量的点的个数进行分类有

g(i) = Σ(C(i-1, k-1)*f(k)*h(i-k))( 1<=k < i)

f(i) = h(i)-g(i)

import java.math.BigInteger;
import java.util.Scanner;

public class Main {
	  static int MAXN = 50;
	  public static void main(String[] args){
		  	BigInteger f[] = new BigInteger [MAXN+10], 
		  			   h[] = new BigInteger [MAXN+10],
		  			   g[] = new BigInteger [MAXN+10],
		  			   C[][] = new BigInteger [MAXN+10][MAXN+10];
		    BigInteger two = new BigInteger("2");
		    C[0][0] = new BigInteger("1");
		    f[0] = h[0] = new BigInteger("1");
		    for(int i = 1; i <= MAXN; ++i){
		    	C[i][0] = C[i][i] = new BigInteger("1");
		    	h[i] = two.pow(i*(i-1)/2);
		    	g[i] = new BigInteger("0");
		    	for(int j = 1; j < i; ++j)
		    		C[i][j] = C[i-1][j].add(C[i-1][j-1]);
		    	for(int j = 1; j < i; ++j)
		    		g[i] = g[i].add(C[i-1][j-1].multiply(f[j].multiply(h[i-j])));
		    	f[i] = h[i].subtract(g[i]);
		    }
		    int n;
		    Scanner sc = new Scanner(System.in);
		    while(sc.hasNextInt())
		    {
		    	n = sc.nextInt();
		    	System.out.println(f[n]);
		    }
	  }
}	    


你可能感兴趣的:(带标号的连通图计数)