zoukankan      html  css  js  c++  java
  • 2019CCPC湖南全国邀请赛 I Neko and tree 树形dp

    dp[ i ][ j ] 表示在 i 这棵子树中, 距离 i 最远点的距离为 j 的方案数。

    转移应该挺显然的把, 记一下mxd[ u ] 表示 u 这颗子树的最大深度, 然后两个for套在一起复杂度就对了。

    #include<bits/stdc++.h>
    #define LL long long
    #define LD long double
    #define ull unsigned long long
    #define fi first
    #define se second
    #define mk make_pair
    #define PLL pair<LL, LL>
    #define PLI pair<LL, int>
    #define PII pair<int, int>
    #define SZ(x) ((int)x.size())
    #define ALL(x) (x).begin(), (x).end()
    #define fio ios::sync_with_stdio(false); cin.tie(0);
    
    using namespace std;
    
    const int N = 5000 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 1e9 + 7;
    const double eps = 1e-8;
    const double PI = acos(-1);
    
    template<class T, class S> inline void add(T& a, S b) {a += b; if(a >= mod) a -= mod;}
    template<class T, class S> inline void sub(T& a, S b) {a -= b; if(a < 0) a += mod;}
    template<class T, class S> inline bool chkmax(T& a, S b) {return a < b ? a = b, true : false;}
    template<class T, class S> inline bool chkmin(T& a, S b) {return a > b ? a = b, true : false;}
    
    int f[N][N];
    int g[N];
    int c[N];
    int n, m, k;
    bool is[N];
    int mxd[N];
    
    vector<int> G[N];
    
    void dfs(int u, int fa) {
        for(auto& v : G[u]) {
            if(v == fa) continue;
            dfs(v, u);
            chkmax(mxd[u], mxd[v] + 1);
            memcpy(g, f[u], sizeof(g));
            for(int i = 0; i <= mxd[u] && i <= k; i++) {
                for(int j = 0; j <= mxd[v] && j <= k; j++) {
                    if(i + j + 1 <= k) {
                        add(g[max(i, j + 1)], 1LL * f[u][i] * f[v][j] % mod);
                    }
                }
            }
            for(int j = 0; j <= mxd[v]; j++) add(g[j + 1], f[v][j]);
            for(int i = 0; i <= mxd[u]; i++) f[u][i] = g[i];
        }
        if(is[u]) {
            f[u][0] = 1;
            for(int i = 1; i <= mxd[u] && i <= k; i++) add(f[u][i], f[u][i]);
        }
    }
    
    int main() {
        scanf("%d%d%d", &n, &m, &k);
        for(int i = 2; i <= n; i++) {
            int u, v;
            scanf("%d%d", &u, &v);
            G[u].push_back(v);
            G[v].push_back(u);
        }
        for(int i = 1; i <= m; i++) {
            int x; scanf("%d", &x);
            is[x] = true;
        }
        dfs(1, 0);
        int ans = 0;
        for(int i = 0; i <= mxd[1]; i++)
            add(ans, f[1][i]);
        printf("%d
    ", ans);
        return 0;
    }
    
    /*
    */
  • 相关阅读:
    CSUFT 1002 Robot Navigation
    CSUFT 1003 All Your Base
    Uva 1599 最佳路径
    Uva 10129 单词
    欧拉回路
    Uva 10305 给任务排序
    uva 816 Abbott的复仇
    Uva 1103 古代象形文字
    Uva 10118 免费糖果
    Uva 725 除法
  • 原文地址:https://www.cnblogs.com/CJLHY/p/10890357.html
Copyright © 2011-2022 走看看