zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    LeetCode: Number Complement
    LeetCode: Hamming Distance
    LeetCode: Sum of Left Leaves
    LeetCode: Ransom Note
    LeetCode: Minimum Moves to Equal Array Elements
    LeetCode: Linked List Random Node
    LeetCode: Product of Array Except Self
    LeetCode:Two Sum II
    LeetCode: Minimum Moves to Equal Array Elements II
    杂记 -- 时间段内应用程序调用次数限制
  • 原文地址:https://www.cnblogs.com/fenice/p/5551490.html
Copyright © 2011-2022 走看看