pku1737给定点求连通图的个数

【题目链接】http://poj.org/problem?id=1737

 

【题目大意】给定一个数n(1<=n<=50),求这n个点构成连通图的方法种数。

 

【分析】

贴下别人的部分题解:

利用补集转化思想, 若不考虑连通性,则有n个点的任意图有G(n)=2^C(n, 2)个. 只要求出不连通图的个数就知道答案F(n). 考虑含结点1的连通块C, |C| = k. 由于不连通,有k < n成立. 则有C(n - 1, k – 1)种方法选择另k-1个结点与结点1组成C. 所以有C(n - 1, k – 1) * F(k)种方法组成C. 剩下的结点组成一个任意图即可. 答案为:

 

 

 

 

(以上可以作为结论,以后可能用到)

我们整个代码过程,就是先求出组合数,然后是g[]数组,最后是f[]数组,求f[]数组过程中公式里的k是从1到n-1。由于数据量大,整个过程必须用到高精度。

 

【代码】

 

/*1737 Accepted 1420K 32MS C++ 5274B 2011-02-05 21:06:26 */
#include<stdio.h>
#include<string.h>
#include"bigint.h"
int f[52][200],g[52][200],c[52][52][200];
int Tmp[200],tmp[200],sum[200];
void Cal_comb(){//计算组合数;
    int i,j;
    copy(c[1][1],ONE),copy(c[1][0],ONE),copy(c[0][0],ONE);
    for(i=2;i<50;i++){
        copy(c[i][0],ONE), copy(c[i][i],ONE);
        for(j=1;j<i;j++)
            add(c[i-1][j-1],c[i-1][j],c[i][j]);
    }  
    //PN(c[10][9]);
}         
void Init_gn(){
    int i,tim;
    copy(g[1],ONE),add(ONE,ONE,g[2]),copy(tmp,g[2]);
    for(i=3;i<=50;i++){
        copy(sum,ONE);
        tim=i*(i-1)/2; //幂次;
        while(tim--){
             copy(Tmp,ZERO);
             mult(tmp,sum,Tmp);
             copy(sum,Tmp);
        }
        copy(g[i],sum); 
    }

void Init_fn(){
    int i,j;
    copy(f[1],ONE), copy(f[2],ONE);
    for(i=3;i<=50;i++){
        copy(sum,ZERO);
        for(j=1;j<i;j++){
            mult(f[j],g[i-j],tmp);
            mult(tmp,c[i-1][j-1],Tmp);
            add(Tmp,sum,tmp);
            copy(sum,tmp);
        }
        sub(g[i],sum,f[i]);
    }
}                   
int main()
{
    int n,i,j,k;
    Cal_comb();
    Init_gn();
    Init_fn();
    //PN(f[12]); printf("%d/n",f[12][0]); //93
    //PN(g[12]); printf("%d/n",g[12][0]);
    while(scanf("%d",&n),n)
        PN(f[n]);
}   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值