tree standings 樹 && dp



#include <bits/stdc++.h>
using namespace std ;
#define MAXN 200
#define MOD  1000000007

typedef enum
{
    NO_STANDS     = 0,
    SAFE_STANDS   = 1,
    NOT_SAFE_STANDS = 2
} state_t;

int counts[MAXN][MAXN + 1][3], aux[MAXN][MAXN + 1][3], neighbours[MAXN][MAXN], n_neighbours[MAXN];

int remove_back_edges(int v, int u)
{
    int i = 0;
    while (i < n_neighbours[v])
    {
        if (neighbours[v][i] == u)
            neighbours[v][i] = neighbours[v][ -- n_neighbours[v]] ;
        else
            remove_back_edges(neighbours[v][i++], v);
    }
}

void count_combinations(int u, int k)
{
    int i, j, l, v;

    for (i = 0; i < n_neighbours[u]; i++)
        count_combinations(neighbours[u][i], k);
    
    
    
    memset(aux, 0, 3 * MAXN * (MAXN + 1) * sizeof(int));

    // "Base case" making the following for-loop accumulate counts.
    aux[0][0][NO_STANDS] = 1;

    for (i = 0; i < n_neighbours[u]; i++)
    {
        v = neighbours[u][i];

        for (j = 0; j <= k; j++)
        {
            for (l = 0; l <= j; l++)
            {
                aux[i + 1][j][NO_STANDS] += ((long long) aux[i][j - l][NO_STANDS] * counts[v][l][NO_STANDS]) % MOD;
                aux[i + 1][j][NO_STANDS] %= MOD;

                aux[i + 1][j][SAFE_STANDS] += ((long long) aux[i][j - l][NO_STANDS] * counts[v][l][SAFE_STANDS]) % MOD;
                aux[i + 1][j][SAFE_STANDS] %= MOD;

                aux[i + 1][j][NOT_SAFE_STANDS] += ((long long) aux[i][j - l][NO_STANDS] * counts[v][l][NOT_SAFE_STANDS]) % MOD;
                aux[i + 1][j][NOT_SAFE_STANDS] %= MOD;

                /**************************************************/

                aux[i + 1][j][SAFE_STANDS] += ((long long) aux[i][j - l][SAFE_STANDS] * counts[v][l][NO_STANDS]) % MOD;
                aux[i + 1][j][SAFE_STANDS] %= MOD;

                aux[i + 1][j][SAFE_STANDS] += ((long long) aux[i][j - l][SAFE_STANDS] * counts[v][l][SAFE_STANDS]) % MOD;
                aux[i + 1][j][SAFE_STANDS] %= MOD;

                aux[i + 1][j][NOT_SAFE_STANDS] += ((long long) aux[i][j - l][SAFE_STANDS] * counts[v][l][NOT_SAFE_STANDS]) % MOD;
                aux[i + 1][j][NOT_SAFE_STANDS] %= MOD;

                /**************************************************/

                aux[i + 1][j][NOT_SAFE_STANDS] += ((long long) aux[i][j - l][NOT_SAFE_STANDS] * counts[v][l][NO_STANDS]) % MOD;
                aux[i + 1][j][NOT_SAFE_STANDS] %= MOD;

                aux[i + 1][j][NOT_SAFE_STANDS] += ((long long) aux[i][j - l][NOT_SAFE_STANDS] * counts[v][l][SAFE_STANDS]) % MOD;
                aux[i + 1][j][NOT_SAFE_STANDS] %= MOD;

                aux[i + 1][j][NOT_SAFE_STANDS] += ((long long) aux[i][j - l][NOT_SAFE_STANDS] * counts[v][l][NOT_SAFE_STANDS]) % MOD;
                aux[i + 1][j][NOT_SAFE_STANDS] %= MOD;
            }
        }
    }


    /* Meaning behind all of this:
     * ===========================
     * aux[n_neighbours[u]][k][NO_STANDS] - number of ways to place `k` stands in the tree rooted at node `u`,
     *                                      where no stand is  placed at `u` or at root of any of its subtrees
     *
     * aux[n_neighbours[u]][k][SAFE_STANDS] - number of ways to place `k` stands in the tree rooted at node `u`,
     *                                        where no stand is placed at `u` and all stands placed at roots of
     *                                        its subtrees are "safe" (they are incident to yet another stand
     *                                        down the tree)
     *
     * aux[n_neighbours[u]][k][NOT_SAFE_STANDS] - number of ways to place `k` stands in the tree rooted at node `u`,
     *                                            where no stand is placed at `u` and not all stands placed at the
     *                                            roots of its subtrees are "safe" (i.e. there is at least one, that
     *                                            is not incident with another stand down the tree)
     *
     * In case of `counts`, the enum values should be interpreted in singular.
     *
     * counts[u][k][NO_STANDS] - number of ways to place `k` stands in the tree rooted at node `u`,
     *                           where no stand is placed at `u`.
     *
     * counts[u][k][SAFE_STANDS] - number of ways to place `k` stands in the tree rooted at node `u`,
     *                             where a stand is placed at `u` and it is adjacent with another stand
     *                             placed at a root of one of its subtrees (i.e. it is "safe").
     *
     * counts[u][k][NOT_SAFE_STANDS] - number of ways to place `k` stands in the tree rooted at node `u`,
     *                                 where a stand is placed at `u` but no stand is place at any root
     *                                 of it subtrees.
     */

    // Base case (trivial solution).
    counts[u][0][NO_STANDS] = 1;

    for (i = 1; i <= k; i++)
    {
        counts[u][i][NO_STANDS] = (aux[n_neighbours[u]][i][NO_STANDS] + aux[n_neighbours[u]][i][SAFE_STANDS]) % MOD;
        counts[u][i][SAFE_STANDS] = (aux[n_neighbours[u]][i - 1][SAFE_STANDS] + aux[n_neighbours[u]][i - 1][NOT_SAFE_STANDS]) % MOD;
        counts[u][i][NOT_SAFE_STANDS] = aux[n_neighbours[u]][i - 1][NO_STANDS];
    }
}

int solve(int k)
{
    remove_back_edges(0, -1);
    
    count_combinations(0, k);

    return (counts[0][k][NO_STANDS] + counts[0][k][SAFE_STANDS]) % MOD;
}
///n_neighbours[]  number of point s  degree
int main()
{
    int i, u, v, N, K;
    while (~ scanf("%d %d", &N, &K)){
        memset(n_neighbours, 0, MAXN * sizeof(int));

        for (i = 0; i < N - 1; i++)
        {
            scanf("%d %d", &u, &v);
            -- u;
            -- v;
            neighbours[u][n_neighbours[u]++] = v;
            neighbours[v][n_neighbours[v]++] = u;
        }

        printf("%d\n", solve(K));
    }
    return 0;
}

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