您的位置:首页 > 其它

poj1737 Connected Graph(组合数学)

2016-08-15 17:36 387 查看
题意:

就是给出结点个数,这些结点都认为是不一样的,要你求出这些点能组成多少种无向图的全连通图

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)


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.



求n个带标号的点组成的连通图的数目。

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


AC代码:

#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
);

    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
);

    }

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: