题意:
就是给出结点个数,这些结点都认为是不一样的,要你求出这些点能组成多少种无向图的全连通图
f(n)表示n个结点共有多少种方案。
n个结点的总方案数为H[C(n,2)]=2^C(n,2);
然后排除不连通的情况,设与结点1连通的点数为k个,这k个点从n-1个点中选取,而包含1的k+1个结点是个连通图,所以有C(n-1, k) * f(k+1)方案
而剩下的n-k-1个结点各点之间任意连接方案数为2^C(n-k-1, 2),所以总的不连通的方案数为C(n-1, k) * f(k+1) * 2^C(n-k-1, 2)
所以f(n) = 2^C(n,2) -sum( C(n-1, k) * f(k+1) * 2^C(n-k-1, 2)); 0 <=k <= n-1
因为数值很大,要用到大整数
这里求C(n,k)用到公式C(n,k) = C(n-1, k) + C(n-1, k-1)
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
Output
Sample Input
1 2 3 4 0
Sample Output
1 1 4 38
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <vector>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <queue>
#define maxn 405
#define INF 999999999
#define LL long long
using namespace std;
int C[60][60][500];
int f[60][500];
int H[2000][500];
void print(int *a)
{
int n = a[0];
printf("%d", a[--n]);
for (--n; n; n--) printf("%04d", a[n]);
printf("\n");
}
const int base = 1e4;
void largemul(int *a, int *b, int *ans)
{
memset(ans, 0, sizeof(int)*(a[0] + b[0]));
for (int i = 1; i < a[0]; i++)
{
for (int j = 1; j < b[0]; j++)
{
ans[i + j - 1] += a[i] * b[j];
ans[i + j] += ans[i + j - 1] / base;
ans[i + j - 1] %= base;
}
}
int &l = ans[0];
l = a[0] + b[0] - 2;
while (l > 1 && !ans[l]) l--;
l++;
}
void larget(int *a, int x)
{
a[0] = 2;
a[1] = x;
}
void largeplus(int *a, int *b, int *ans)
{
int l = max(a[0], b[0]);
memset(ans, 0, sizeof(int)*(l + 1));
for (int i = 1; i < l; i++)
{
if (i >= a[0]) a[i] = 0;
if (i >= b[0]) b[i] = 0;
ans[i] += a[i] + b[i];
ans[i + 1] += ans[i] / base;
ans[i] %= base;
}
ans[0] = (ans[l] ? l + 1 : l);
}
void largesub(int *a, int *b, int *ans)
{
memset(ans, 0, sizeof(int)*(a[0] + 1));
for (int i = 1; i < a[0]; i++)
{
if (i >= b[0]) b[i] = 0;
ans[i] += a[i] - b[i];
if (ans[i] < 0)
{
ans[i] += base;
ans[i + 1]--;
}
}
ans[0] = a[0];
while (ans[0] > 1 && !ans[ans[0] - 1]) ans[0]--;
}
void pre()
{
larget(H[0], 1);
for (int i = 1; i <= 1225; i++)
largeplus(H[i - 1], H[i - 1], H[i]);
for (int i = 0; i <= 50; i++)
{
larget(C[i][0], 1);
larget(C[i][i], 1);
for (int j = 1; j < i; j++)
largeplus(C[i - 1][j], C[i - 1][j-1], C[i][j]);
}
}
void inti()
{
larget(f[1], 1);
for (int i = 2; i <= 50; i++)
{
int aa1[500], aa2[500], aa3[500];
int *a1 = aa1, *a2 = aa2, *a3 = aa3;
larget(a3, 0);
for (int j = 0; j < i - 1; j++)
{
largemul(C[i - 1][j], f[j + 1], a1);
largemul(a1, H[(i - j - 1)*(i - j - 2) / 2], a2);
largeplus(a2, a3, a1);
swap(a1, a3);
}
largesub(H[i*(i - 1) / 2], a3, f[i]);
}
}
int main()
{
int n;
pre();
inti();
while (scanf("%d", &n) && n)
{
print(f[n]);
}
}