码迷,mamicode.com
首页 > 其他好文 > 详细

[HAOI2015]树上染色

时间:2019-01-02 19:17:22      阅读:173      评论:0      收藏:0      [点我收藏+]

标签:min   str   type   org   树形dp   eps   pac   string   last   

嘟嘟嘟


首先这一眼看出来,要树形dp。
然后发现状态不好设,刚开始我想的是dp[i][j]表示以\(i\)为根的子树,选了\(j\)个黑点的最大价值。结果就不会转移了。
转移的时候想考虑\(<u, v, w>\)这一条边的贡献,但是发现这个状态的转移所涉及的不只是这一条边,还有子树中的边,于是就彻底gg了。
还是看了题解。
题解也是考虑贡献,而且也是考虑每一条边,但最大的区别是,我们枚举边,然后考虑边两侧的点对答案的贡献。
令dp[i][j]表示以\(i\)为根的子树,选了\(j\)个黑点,已经枚举到第\(x\)条边时,当前答案的最大值。
因为dfs的时候就相当于枚举边了,所以这一维自然省去。
于是对于黑点,有\(j * (K - j) * w(u, v)\)的贡献,
对于白点,有\((K - j) * (n - size[v] - (K - j)) * w(u, v)\)的贡献。
最后记得要初始化dp数组为-INF,因为有些状态不合法。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define enter puts("") 
#define space putchar(‘ ‘)
#define Mem(a, x) memset(a, x, sizeof(a))
#define In inline
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-8;
const int maxn = 2e3 + 5;
inline ll read()
{
    ll ans = 0;
    char ch = getchar(), last = ‘ ‘;
    while(!isdigit(ch)) {last = ch; ch = getchar();}
    while(isdigit(ch)) {ans = (ans << 1) + (ans << 3) + ch - ‘0‘; ch = getchar();}
    if(last == ‘-‘) ans = -ans;
    return ans;
}
inline void write(ll x)
{
    if(x < 0) x = -x, putchar(‘-‘);
    if(x >= 10) write(x / 10);
    putchar(x % 10 + ‘0‘);
}

int n, K;
struct Edge
{
    int nxt, to; ll w;
}e[maxn << 1];
int head[maxn], ecnt = -1;
In void addEdge(int x, int y, ll w)
{
    e[++ecnt] = (Edge){head[x], y, w};
    head[x] = ecnt;
}

int siz[maxn];
ll dp[maxn][maxn];
In void dfs(int now, int _f)
{
    siz[now] = 1; dp[now][0] = dp[now][1] = 0;
    for(int i = head[now], v; i != -1; i = e[i].nxt)
    {
        if((v = e[i].to) == _f) continue;
        dfs(v, now);
        siz[now] += siz[v];
        for(int j = min(siz[now], K); j >= 0; --j)
            for(int k = 0; k <= min(j, siz[v]); ++k)
                dp[now][j] = max(dp[now][j], dp[now][j - k] + dp[v][k] + 1LL * k * (K - k) * e[i].w + 1LL * (siz[v] - k) * (n - siz[v] - K + k) * e[i].w);
    }
}

int main()
{
    Mem(head, -1);
    n = read(); K = read();
    for(int i = 1; i < n; ++i)
    {
        int x = read(), y = read(); ll w = read();
        addEdge(x, y, w); addEdge(y, x, w);
    }
    for(int i = 1; i <= n; ++i) fill(dp[i] + 1, dp[i] + K + 1, INF);
    //带劲的操作 
    dfs(1, 0);
    write(dp[1][K]), enter;
    return 0;
}

[HAOI2015]树上染色

标签:min   str   type   org   树形dp   eps   pac   string   last   

原文地址:https://www.cnblogs.com/mrclr/p/10209710.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!