zoukankan      html  css  js  c++  java
  • HAOI2015 树上染色

    传送门

    非常神奇的树形DP……

    可能和大多数人一样吧,一开始我令dp[i][j]表示以i为根的子树选择j个黑点的最大价值,之后就不会转移了……

    后来发现这个状态设的并不对,因为我们要考虑的是对答案的总贡献,而不是每个子树内的价值,也就是我们要考虑的是每条边对答案的贡献。

    这个式子很显然的,但是像我这样是肯定考虑不到的……

    于是就把这个问题转化成了树上背包,我们把在子树内选取的黑点看作体积,贡献看作价值,之后我们进行DP即可。注意这道题的关键是,对于答案的贡献并不只局限于子树内,而是对于整棵树而言。

    令dp[i][j]表示以i为根的子树选择j个黑点的最大贡献,那么dp[i][j] = max(dp[i][j],dp[i][t] + dp[v][j-t] + val),val是计算的贡献。

    这样进行DP就可以啦。

    看一下代码。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<set>
    #include<queue>
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    
    using namespace std;
    typedef long long ll;
    const int M = 2005;
    const int INF = 1000000009;
    
    ll read()
    {
        ll ans = 0,op = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
        if(ch == '-') op = -1;
        ch = getchar();
        }
        while(ch >= '0' && ch <= '9')
        {
        ans *= 10;
        ans += ch - '0';
        ch = getchar();
        }
        return ans * op;
    }
    
    struct edge
    {
        int next,to;
        ll v;
    }e[M<<1];
    
    ll dp[M][M],ans,x,y,z,ecnt,head[M];
    int size[M],n,k;
    
    void add(int x,int y,int z)
    {
        e[++ecnt].to = y;
        e[ecnt].next = head[x];
        e[ecnt].v = z;
        head[x] = ecnt;
    }
    
    void dfs(int x,int fa)
    {
        size[x] = 1,dp[x][0] = dp[x][1] = 0;
        for(int i = head[x];i;i = e[i].next)
        {
        if(e[i].to == fa) continue;
        dfs(e[i].to,x);
        size[x] += size[e[i].to];
        }
        for(int i = head[x];i;i = e[i].next)
        {
        int v = e[i].to;
        if(v == fa) continue;
        per(j,min(k,size[x]),0)
            rep(p,0,min(j,size[v]))
        {
            if(dp[x][j-p] != -1)
            {
            ll val = (ll)(e[i].v * p * (k-p)) + (ll)(e[i].v * (size[v] - p) * (n-k+p-size[v]));
            dp[x][j] = max(dp[x][j],dp[v][p] + dp[x][j-p] + val);
            }
        }    
        }
    }
    
    int main()
    {
        n = read(),k = read();
        memset(dp,-1,sizeof(dp));
        rep(i,1,n-1) x = read(),y = read(),z = read(),add(x,y,z),add(y,x,z);
        dfs(1,0);
        printf("%lld
    ",dp[1][k]);
        return 0;
    }
  • 相关阅读:
    获取label标签内for的属性值-js
    js万亿级数字转汉字的封装方法
    a标签的伪元素的应用——link,hover,visited,active
    JS声明变量的写法
    VUE环境配置步骤及相关Git Bash命令的使用
    display:inline-block下,元素不能在同一水平线及元素间无margin间距的问题解决方法
    css变量的用法——(--cssName)
    img的属性alt 与 title的区别
    返回结果的HTTP状态码——《图解http》第四章
    HTTP报文内部的HTTP信息——《图解HTTP》第三章
  • 原文地址:https://www.cnblogs.com/captain1/p/9823575.html
Copyright © 2011-2022 走看看