POJ - 1737 Connected Graph

题目来源:http://poj.org/problem?id=1737

设f[n]表示n个点的连通图的个数。可以考虑n个点组成的所有图的总方案数减去不连通的方案数得到最终结果。

总方案数为2^n*(n-1)/2。

不连通的方案数:

  考虑1号节点所处的联通块的节点个数,假设当前连通块内节点个数为k,那么该联通块的组成情况可能有f[k]*c[n-1][k-1]种,c表示组合数。其余节点共有n-k个,与连通块没有任何边相连,这n-k个点内部的组成情况可能有2^(n-k)*(n-k-1)/2种。

  因此,f[n]=Σ2^n*(n-1)/2 - f[k]*c[n-1][k-1]*2^(n-k)*(n-k-1)。

数据很大,需要用高精度大整数。

代码:

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

public class Main {

    static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));

    static int nextInt() throws IOException {
        in.nextToken();
        return (int) in.nval;
    }

    static double nextDouble() throws IOException {
        in.nextToken();
        return in.nval;
    }

    static long nextLong() throws IOException {
        in.nextToken();
        return (long) in.nval;
    }

    static String next() throws IOException {
        in.nextToken();
        return in.sval;
    }

    static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));

    static BigInteger f[], c[][];

    static BigInteger pow_mod(BigInteger a, long b) {
        BigInteger ans = BigInteger.ONE;
        while (b > 0) {
            if ((b & 1) != 0) ans = ans.multiply(a);
            a = a.multiply(a);
            b >>= 1;
        }
        return ans;
    }

    public static void main(String[] args) throws IOException {
        f = new BigInteger[51];
        c = new BigInteger[51][51];
        for (int i = 1; i <= 50; ++i) f[i] = BigInteger.ZERO;
        for (int i = 1; i <= 50; ++i) {
            for (int j = 0; j <= i; ++j) {
                if (j == 0 || j == i || i == 1) c[i][j] = BigInteger.ONE;
                else c[i][j] = c[i - 1][j].add(c[i - 1][j - 1]);
            }
        }
        BigInteger TWO = new BigInteger("2");
        for (int n = 1; n <= 50; ++n) {
            for (int k = 1; k < n; ++k) {
                f[n] = f[n].subtract(f[k].multiply(c[n - 1][k - 1].multiply(pow_mod(TWO, (n - k) * (n - k - 1) / 2))));
            }
            f[n] = f[n].add(pow_mod(TWO, n * (n - 1) / 2));
        }
        int x;
        while (in.nextToken() != in.TT_EOF) {
            x = (int) in.nval;
            if (x == 0) break;
            out.println(f[x]);
        }
        out.flush();
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值