pku 1737 Connected Graph 组合数学,图的计数问题注意联系连通分量

题目意思很明了,计算一个n个顶点的无向连通图的数量
可以这样思考:
n个顶点的无相连通图构成方法为在n-1个节点中分离出一个大小为i的联通分量加上第n个节点与剩余的n-1-i个点构成的联通分量(可能n-1-i个点并不联通,但是可以通过第n个点联通),所以初步的式子是这样:
dp[i]=sum{dp[j]*(1 shl j-1)*dp[i-j]*c[j-1][i]}
但是这个式子有点问题,会产生重复,如图所示

1)

    2

 

 

 

1)和2)其实是同一种状态,但是按 算选出(12)是一种,选出(34)是一种,所以产生了重复。

那么该怎么修改呢,其实只要固定一个点,假设是1,再从n-1个点中选出i-1个点去跟1构成连通图即Ci-1n-1,那样就可以避免重复了;

所以式子修正为

dp[i]=sum{dp[j]*(1 shl j-1)*dp[i-j]*c[j-2][i-1]}
不知道网上很多人为什么要从反面考虑,即算出n无向图的个数2^C[n][2]然后再减去不连通的诱导子图数目,感觉是多此一举~
 1 import java.io.*;
 2 import java.math.*;
 3 public class Main {
 4 
 5     /**
 6      * @param args
 7      */
 8     public static void main(String[] args) throws IOException{
 9         BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
10         BigInteger dp[]=new BigInteger[60];
11         BigInteger c[][]=new BigInteger[51][51];
12         c[0][0]=BigInteger.ONE;
13         for(int i=1;i<=50;i++)
14             c[i][0]=c[i][i]=BigInteger.ONE;
15         for(int i=2;i<=50;i++)
16             for(int j=1;j<i;j++)
17                 c[i][j]=c[i-1][j].add(c[i-1][j-1]);
18         dp[1]=BigInteger.ONE;
19         dp[0]=BigInteger.ONE;
20         for(int i=2;i<=50;i++)
21         {
22             dp[i]=BigInteger.ZERO;
23             for(int j=1;j<i;j++)
24                 dp[i]=dp[i].add(dp[j].multiply((BigInteger.ONE.shiftLeft(j)).add(BigInteger.ONE.negate())).multiply(dp[i-j]).multiply(c[i-2][j-1]));
25         }
26         int num=0;
27         while(true)
28         {
29             num=Integer.parseInt(in.readLine());
30             if(num==0break;
31             System.out.println(dp[num]);
32         }
33 
34     }
35 
36 }
37 


posted on 2010-10-27 23:47 yzhw 阅读(363) 评论(0)  编辑 收藏 引用 所属分类: graphcombination math


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2010年11月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

导航

统计

公告

统计系统

留言簿(1)

随笔分类(227)

文章分类(2)

OJ

最新随笔

搜索

积分与排名

最新评论

阅读排行榜