首页 > 其他 > 详细

[HAOI2015]树上染色

时间:2019-10-19 22:12:07      阅读:57      评论:0      收藏:0      [点我收藏+]

两点之间贡献和的问题转化成边的贡献

已经深搜过的点的个数为son[u] 回溯得到的另外一个子树的个数为son[v]

然后每一条边的贡献分别由黑点和白点组成

设遍历到的树边靠近子树的一端黑点为x, 即 黑内为x 黑外 为 K - x 那么黑点的贡献为x * (son[v] - x)

白内为 son[v] - x 白外为(n - son[v]  - (  son[v] - x ) ) 白点的贡献为 前面两者相乘

 

#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>

typedef long long ll;
using namespace std;

const ll inf = 0x3f3f3f3f;

using namespace std;
const ll maxn = 2e3+10;
const ll maxm = 2e3+10;
struct node {
    ll v, w;
    ll nxt;
}edge[maxm * 2];
ll head[maxn], tot;
void Insert(ll u, ll v, ll w) {
    edge[++tot].v = v;
    edge[tot].w = w;
    edge[tot].nxt = head[u];
    head[u] = tot;
}
ll son[maxn];
ll n, m, K;
ll dp[maxn][maxn];
ll f(ll x, int num, int v) {
    return x * num * (K - num) + x * (n - son[v] - (K - num)) * (son[v] - num);
}
void dfs(ll u) {
    son[u] = 1;
    for (ll i = head[u]; i; i = edge[i].nxt) {
        int v = edge[i].v;
        if (son[v]) {continue;}
        dfs(v);
        for (ll j = min(son[u], K); j >= 0; j--) {
            for (int k = min(K, son[v]); k >= 0; k--)
                dp[u][j + k] = max(dp[u][j + k], dp[u][j] + dp[v][k] + f(edge[i].w, k, v));
        }
        son[u] += son[v];
    }
}


int main () {
    scanf("%lld%lld", &n, &K);
    for (ll i = 1; i < n; i++) {
        ll u, v, w;
        scanf("%lld%lld%lld", &u, &v, &w);
        Insert(u, v, w);
        Insert(v, u, w);
    }
    dfs(1);
    printf("%lld\n", dp[1][K]);
    return 0;
} 

 

[HAOI2015]树上染色

原文:https://www.cnblogs.com/Urchin-C/p/11705831.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!