• HDU 5629 Clarke and tree dp+prufer序列


    题目链接:

    http://acm.hdu.edu.cn/showproblem.php?pid=562

    题意:

    求给每个节点的度数允许的最大值,让你求k个节点能组成的不同的生成树个数。

    题解:

    对于n个节点形成的一颗生成树,有一个与之唯一对应的大小为n-2的prufer数列。

    并且一个节点的度数减一为它出现在prufer数列中的次数。

    那么我们求生成树的个数可以转化为求prufer数列的可重集排列,而这个可以用dp来做。

    dp[i][j][k]表示处理到第i个节点,已经用了j个节点,且可重集大小为k的排列组合数。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    
    const int maxn = 55;
    const int mod = 1e9 + 7;
    typedef long long LL;
    
    int n;
    LL dp[maxn][maxn][maxn];
    int arr[maxn];
    
    LL C[maxn][maxn];
    void pre() {
        C[0][0] = 1;
        for (int i = 1; i < maxn; i++) {
            C[i][0] = 1;
            for (int j = 1; j <= i; j++) {
                C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % mod;
            }
        }
    }
    
    void init() {
        memset(dp, 0, sizeof(dp));
    }
    
    int main() {
        pre();
        int tc;
        scanf("%d", &tc);
        while (tc--) {
            init();
            scanf("%d", &n);
            for (int i = 1; i <= n; i++) {
                scanf("%d", &arr[i]);
            }
            dp[0][0][0] = 1;
            for (int i = 0; i <= n; i++) {
                for (int j = 0; j <= i; j++) {
                    for (int k = 0; k <= n - 2; k++) {
                        //不用第i+1个数
                        dp[i + 1][j][k] = (dp[i + 1][j][k] + dp[i][j][k]) % mod;
                        //用第i+1个数
                        for (int l = 1; l <= arr[i + 1] && l - 1 + k <= n - 2; l++) {
                            dp[i + 1][j + 1][k + l - 1] = (dp[i + 1][j + 1][k + l - 1] + C[k + l - 1][l - 1] * dp[i][j][k]) % mod;
                        }
                    }
                }
            }
            printf("%d", n);
            for (int i = 2; i <= n; i++) printf(" %lld", dp[n][i][i - 2]);
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    各种素材类精品网站
    Java如何设置代理ip
    Spring事务的实现方式和原理以及隔离级别?
    Spring 是什么?
    线程池中阻塞队列的作用?为什么是先添加队列而不是先创建最大线程?
    为什么用线程池?解释下线程池参数
    并发三大特性
    ThreadLocal的原理和使用场景。
    谈谈对线程安全的理解
    sleep,wait,join,yield
  • 原文地址:https://www.cnblogs.com/fenice/p/5551490.html
Copyright © 2020-2023  润新知