【POJ1737】Connected Graph

                                                Connected Graph

Time Limit: 1000MS   Memory Limit: 30000K
Total Submissions: 3691   Accepted: 1770

Description

An undirected graph is a set V of vertices and a set of E∈{V*V} edges.An undirected graph is connected if and only if for every pair (u,v) of vertices,u is reachable from v.
You are to write a program that tries to calculate the number of different connected undirected graph with n vertices.
For example,there are 4 different connected undirected graphs with 3 vertices.

Input

The input contains several test cases. Each test case contains an integer n, denoting the number of vertices. You may assume that 1<=n<=50. The last test case is followed by one zero.

Output

For each test case output the answer on a single line.

Sample Input

1
2
3
4
0

Sample Output

1
1
4
38

 

題意:

       求N個點的無向連通圖有多少個。

解析:

       計數類DP。

       N個點的無向圖總數顯然爲2^{N*(N-1)/2}(乘法原理)。

       考慮用總數減去不連通數,一張不連通的無向圖必定由若干個連通塊構成。我們可以枚舉標號爲1的節點所在連通塊包含節點的個數 K,從 2~N 這 N-1 個節點中選出 K-1 個節點構成任意無向圖,有2^{(N-k)*(N-K-1)/2}種選法。

       綜上,令f[i]表示 i 個節點的無向連通圖的個數,於是就有以下狀態轉移方程:

       f[i]=2^{i*(i-1)/2}-\sum_{j=1}^{N-1}f[j]*C_{i-1}^{j-1}*2^{(i-j)*(i-j-1)/2}

       還是容易理解的。

       PS:這題要用高精就真的噁心了。。。

 

代碼:

//created by lyd
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
using namespace std;
int n;
struct H
{int a[400],len;}f[60],power[60];
inline H operator / (const H &x,const int y)
{
	H z;
	memset(z.a,0,sizeof z.a);
	z.len=0;
	int left=0;
	for(int i=x.len;i>=1;i--)
	{
		left=left*10+x.a[i];
		z.a[i]=left/y;
		left%=y;
		if(!z.len&&z.a[i]) z.len=i;
	}
	return z;
}
inline H operator + (const H &x,const H &y)
{
	H z;
	memset(z.a,0,sizeof z.a);
	for(int i=1;i<=max(x.len,y.len);i++)
	{
		z.a[i]+=x.a[i]+y.a[i];
		z.a[i+1]=z.a[i]/10;
		z.a[i]%=10;
	}
	z.len=max(x.len,y.len);
	if(z.a[z.len+1]) z.len++;
	return z;
}
inline H operator * (const H &x,const H &y)
{    
	H z;                     
	memset(z.a,0,sizeof z.a);
	for(int i=1;i<=x.len;i++)
		for(int j=1;j<=y.len;j++)
		{
			z.a[i+j-1]+=x.a[i]*y.a[j];
			z.a[i+j]+=z.a[i+j-1]/10;
			z.a[i+j-1]%=10;	
		}
	z.len=x.len+y.len-1;
	if(z.a[z.len+1]) z.len++;
	return z;
}
inline H C(int x,int y)
{
	H tot,temp;
	tot.len=1;
	tot.a[1]=1;
	for(int i=y,j=1;j<=x;i--,j++)
	{
		int t=i;
		temp.len=0;
		while(t)
		{
			temp.a[++temp.len]=t%10;
			t/=10;
		}
		tot=tot*temp/j;
	}
	return tot;
}
inline void print(const H &x)
{
	for(int i=x.len;i>=1;i--)
		printf("%d",x.a[i]);
	printf("\n");
}
int main()
{
	for(int i=1;i<=50;i++)
	{
		long long temp=((long long)(1)<<i)-1;
		while(temp)
		{
			power[i].a[++power[i].len]=temp%10;
			temp/=10;
		}
	}
	f[1].len=1;f[1].a[1]=1;
	f[2].len=1;f[2].a[1]=1;
	for(int i=3;i<=50;i++)
		for(int j=1;j<=i-1;j++)
			f[i]=f[i]+C(j-1,i-2)*f[j]*f[i-j]*power[j];
	while(scanf("%d",&n),n) print(f[n]);
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章