tree standings 树 && dp

来源:互联网 发布:linux的service命令 编辑:程序博客网 时间:2024/06/05 15:59



#include <bits/stdc++.h>using namespace std ;#define MAXN 200#define MOD  1000000007typedef 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  degreeint 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;}