E. Paint the Tree(树形dp)

Posted starve

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了E. Paint the Tree(树形dp)相关的知识,希望对你有一定的参考价值。

题:https://codeforces.com/contest/1241/problem/E

题目大意:给你一棵树,每一个点都可以染k种颜色,你拥有无数种颜色,每一种颜色最多使用2次,如果一条边的两个节点拥有同一种颜色,那么就说

这条边是饱和的,一个树的价值定义为饱和边的权值之和,问一棵树的最大价值是多少。

技术图片
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pb push_back
const int M=5e5+5;
int head[M],tot,n,k;
vector<ll>val;
ll dp[M][2];
//dp[u][1] 表示这条边用了k种颜色了。
//dp[u][0] 表示这条边用了k-1种颜色。
struct node{
    int v,nextt;
    ll w;
}e[M<<1];
bool cmp(int x,int y){
    return x>y;
}
void addedge(int u,int v,ll w){
    e[tot].v=v;
    e[tot].w=w;
    e[tot].nextt=head[u];
    head[u]=tot++;
}
void dfs(int u,int f){
    dp[u][0]=dp[u][1]=0;
    for(int i=head[u];~i;i=e[i].nextt){
        int v=e[i].v;
        if(v!=f){
            dfs(v,u);
            dp[u][0]+=dp[v][1];
            dp[u][1]+=dp[v][1];
        }
    }
    val.clear();
    for(int i=head[u];~i;i=e[i].nextt){
        int v=e[i].v;
        if(v!=f){//将当前的子节点降到只用了k-1种颜色的最优选择 
            val.pb(dp[v][0]+e[i].w-dp[v][1]);
        }
    }
    sort(val.begin(),val.end(),cmp);
    int len=val.size();
    len=min(len,k);
    for(int i=0;i<len;i++){
        if(val[i]<0)
            break; 
        if(i<k-1)
            dp[u][0]+=val[i];
        
        dp[u][1]+=val[i];
    }
}
int main(){
    int t;
    cin>>t;
    while(t--){
        tot=0;
        scanf("%d%d",&n,&k);
        for(int i=0;i<=n;i++)
            head[i]=-1;
        for(int u,v,i=1;i<n;i++){
            ll w;
            scanf("%d%d%I64d",&u,&v,&w);
            addedge(u,v,w);
            addedge(v,u,w);
        }
        dfs(1,-1);
        printf("%I64d
",max(dp[1][0],dp[1][1]));
    }
    return 0;
}
View Code

 

以上是关于E. Paint the Tree(树形dp)的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #646 (Div. 2) E. Tree Shuffling(贪心/树形DP)

Codeforces1065F Up and Down the Tree 树形DP

CF1244DPaint the Tree(树形DP)

C. Ilya And The Tree 树形dp 暴力

牛客练习赛55 E.树 树形dp

E. Construct the Binary Tree。。。