zoukankan      html  css  js  c++  java
  • [JSOI 2018] 潜入行动

    [题目链接]

             https://www.lydsy.com/JudgeOnline/problem.php?id=5314 

    [算法]

            考虑dp , 用f[i][j][0 / 1][0 / 1]表示以i为根的子树中选了j个 , 是否选i , i是否被覆盖的方案数

            树形背包进行合并 , 转移即可

            时间复杂度 : O(NK)

    [代码]

            

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int MAXN = 1e5 + 10;
    const int MAXK = 110;
    const int P = 1e9 + 7;
    
    struct edge
    {
            int to , nxt;
    } e[MAXN << 1];
    
    int n , K , tot;
    int head[MAXN] , dp[MAXN][MAXK][2][2] , tmp[MAXK][2][2] , size[MAXN];
    
    #define rint register int
    
    template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
    template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
    template <typename T> inline void read(T &x)
    {
        T f = 1; x = 0;
        char c = getchar();
        for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
        for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
        x *= f;
    }
    inline void addedge(int x , int y)
    {
            ++tot;
            e[tot] = (edge){y , head[x]};
            head[x] = tot;
    }
    inline void update(int &x , int y)
    {
            x += y;
            while (x >= P) x -= P;
    }
    inline void dfs(int u , int par)
    {
            size[u] = 1;
            dp[u][0][0][0] = 1;
            dp[u][1][1][0] = 1;
            for (rint i = head[u]; i; i = e[i].nxt)
            {
                    int v = e[i].to;
                    if (v == par) continue;
                    dfs(v , u);
                    for (rint j = min(K , size[u] + size[v]); j >= 0; --j)
                    {
                            tmp[j][1][1] = 0;
                            tmp[j][0][0] = 0;
                            tmp[j][1][0] = 0;
                            tmp[j][0][1] = 0;   
                    }
                    for (rint j = 0; j <= size[u] && j <= K; ++j)
                    {
                            for (rint k = 0; k <= size[v] && j + k <= K; ++k)
                            {
                                    if (dp[u][j][1][1])
                                    {
                                            update(tmp[j + k][1][1] , 1LL * dp[u][j][1][1] * dp[v][k][1][1] % P);
                                            update(tmp[j + k][1][1] , 1LL * dp[u][j][1][1] * dp[v][k][0][1] % P);
                                            update(tmp[j + k][1][1] , 1LL * dp[u][j][1][1] * dp[v][k][1][0] % P);
                                            update(tmp[j + k][1][1] , 1LL * dp[u][j][1][1] * dp[v][k][0][0] % P);
                                    } 
                                    if (dp[u][j][1][0])
                                    {
                                            update(tmp[j + k][1][0] , 1LL * dp[u][j][1][0] * dp[v][k][0][0] % P);
                                            update(tmp[j + k][1][0] , 1LL * dp[u][j][1][0] * dp[v][k][0][1] % P);
                                            update(tmp[j + k][1][1] , 1LL * dp[u][j][1][0] * dp[v][k][1][0] % P);
                                            update(tmp[j + k][1][1] , 1LL * dp[u][j][1][0] * dp[v][k][1][1] % P);
                                    }
                                    if (dp[u][j][0][1])
                                    {
                                            update(tmp[j + k][0][1] , 1LL * dp[u][j][0][1] * dp[v][k][0][1] % P);
                                            update(tmp[j + k][0][1] , 1LL * dp[u][j][0][1] * dp[v][k][1][1] % P);
                                    }
                                    if (dp[u][j][0][0])
                                    {
                                            update(tmp[j + k][0][0] , 1LL * dp[u][j][0][0] * dp[v][k][0][1] % P);
                                            update(tmp[j + k][0][1] , 1LL * dp[u][j][0][0] * dp[v][k][1][1] % P);
                                    }
                            }
                    }        
                    size[u] += size[v];
                    for (int j = min(K , size[u]); j >= 0; --j)
                    {
                            dp[u][j][0][0] = tmp[j][0][0];
                            dp[u][j][0][1] = tmp[j][0][1];
                            dp[u][j][1][0] = tmp[j][1][0];
                            dp[u][j][1][1] = tmp[j][1][1];
                    }
            }        
    }
    
    int main()
    {
            
            read(n); read(K);
            for (rint i = 1; i < n; ++i)
            {
                    int x , y;
                    read(x); read(y);
                    addedge(x , y);
                    addedge(y , x);
            }
            dfs(1 , 0);
            printf("%d
    " , (dp[1][K][0][1] + dp[1][K][1][1]) % P);
            
            return 0;
        
    }
  • 相关阅读:
    机器学习入门-文本数据-使用聚类增加文本的标签属性
    机器学习入门-文本特征-使用LDA主题模型构造标签 1.LatentDirichletAllocation(LDA用于构建主题模型) 2.LDA.components(输出各个词向量的权重值)
    机器学习入门-文本特征-word2vec词向量模型 1.word2vec(进行word2vec映射编码)2.model.wv['sky']输出这个词的向量映射 3.model.wv.index2vec(输出经过映射的词名称)
    机器学习入门-数值特征-对数据进行log变化
    python中datetime.strptime(),strftime()的应用
    css中的','、'>'、'+'、'~'
    js中const,var,let区别
    css的#和.的区别
    js实现拖放
    [Usaco2005]Part Acquisition
  • 原文地址:https://www.cnblogs.com/evenbao/p/10659983.html
Copyright © 2011-2022 走看看