// poj 1737 Connected Graph // // 题目大意: // // 带标号的连通分量计数 // // 解题思路: // // 设f(n)为连通图的数量,g(n)为非连通图的数量,h(n)为所有的 // 图的数量,h(n) = 2 ^(n * (n - 1) / 2); // f(n) + g[n] = h(n). // // 考虑标号为1在哪个连通分量内,设连通分量内有k个点,则问题为 // 在n-1个点中选择k-1个点的方法数 C(n-1,k-1),此时1所在的连通图数 // 为f(k),另一部分为n-k个点的图的所有数量,因为此时已经设了1所在 // 的连通图和剩余部分已经是不连通了,则 // g(n) = sigma(C(n-1,k-1)*f(k)*h(n-k)){ 1<= k <= n-1} // f[n] = h[n] - g[n]; import java.util.*; import java.io.*; import java.math.BigInteger; class Main{ public static void main(String[] args){ final int MAX_N = 55; BigInteger[][] C = new BigInteger[MAX_N][MAX_N]; BigInteger[] f = new BigInteger[MAX_N]; BigInteger[] g = new BigInteger[MAX_N]; BigInteger[] h = new BigInteger[MAX_N]; C[0][0] = new BigInteger("1"); for (int i=1;i<MAX_N;i++){ C[i][0] = C[i][i] = new BigInteger("1"); for (int j=1;j<i;j++){ C[i][j] = new BigInteger("0"); C[i][j] = C[i][j].add(C[i-1][j]); C[i][j] = C[i][j].add(C[i-1][j-1]); } } for (int i=1;i<MAX_N;i++){ h[i] = new BigInteger("2"); h[i] = h[i].pow(i*(i-1)/2); } f[0] = h[0] = new BigInteger("1"); for (int i=1;i<MAX_N;i++){ g[i] = new BigInteger("0"); 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]); } Scanner sc = new Scanner(System.in); while(sc.hasNextInt()){ int x = sc.nextInt(); if (x==0) break; System.out.println(f[x]); } } }
时间: 2024-10-08 05:04:09