题意

  • 对于一个有n个结点的二叉树,根的编号一定为1,每条边有权值
  • 求保留q条边时,最多能获得多少权值
  • tip:分析样例可以知道,这棵树的根是必须保留的,“剪枝行为”一定是保留根含有根的子树

思路(法一)

  • 由于输入是无规律的输入每一条边,所以应当先建立起二叉树,从根开始深搜建树
  • 由于边权是较难处理的,我们发现可以把所有边权变为该条边所连的儿子的权值,把边权转换为点权,同时边转化为点,会多一个点,所以最终保留q条边会变为保留q+1个点
  • 建完这棵树后,可以进行动态规划,对每个结点考虑剩下多少个边,进行枚举
  • 表示i包含j个点(边)
  • 树形dp,dfs深搜即可,每次深搜记录当前结点和剩余结点数,从当前层迭代到下一层只需改变剩余结点数即可

代码

#include<bits/stdc++.h>
using namespace std;

/**
 * dp[i][j]表示i包含j个点(边)
 * dp[i][j]=dp[T[i].l][k]+dp[T[i].r][j-1-k];
 */


typedef struct node{
    int val;
    int l,r;
}tree;
tree T[200];
vector<int> g[150];
int v[150][150];
int dp[150][150];
int n,q;

void push_down(int x,int fa){
    for(auto i : g[x]){
        if(i==fa)continue;

        if(T[x].l==0) T[x].l=i;
        else T[x].r=i;

        T[i].val=v[x][i];            
        push_down(i,x);
    }
}
int dfs(int x,int rst){
    if(x==0) return 0;
    if(dp[x][rst]!=0) return dp[x][rst];
    for(int i=0;i<rst;i++){
        dp[x][rst]=max(dp[x][rst],dfs(T[x].l,i)+dfs(T[x].r,rst-1-i)+T[x].val);
    }
    return dp[x][rst];
}

int main(){
    cin >> n >> q;
    for(int i=1;i<n;i++){
        int a,b,c;
        cin >> a >> b >> c ;
        g[a].push_back(b);
        g[b].push_back(a);
        v[a][b]=v[b][a]=c;
    }
    push_down(1,0);
    // for(int i=1;i<=n;i++){
    //     cout << i << ' ' << T[i].val << ' ' << T[i].l << ' ' << T[i].r << endl;
    // }
    cout << dfs(1,q+1) << endl ;
    return 0;
}

思路(法二)

  • 就硬存每一条边
  • 考虑为背包,把父亲和剩下的看为一部分,把当前及子树看为一部分
  • 注意更新的时候先更新大的部分再更新小的部分,不然大的取最优会取重复

代码

#include<bits/stdc++.h>
using namespace std;
int n,q;
vector<int> g[120];
vector<int> apple[120];
int dp[300][300];
void dfs(int x,int fa){
    dp[x][0]=0;
    for(int id=0;id<g[x].size();id++){
        int i=g[x][id];
        if(i==fa) continue;
        dfs(i,x);
        for(int j=q;j>=0;j--){
            for(int k=0;k<j;k++){
                dp[x][j]=max(dp[x][j],dp[x][j-k-1]+dp[i][k]+apple[x][id]);
            }
        }
    }

}

int main(){
    cin >> n >> q ;
    for(int i=1;i<n;i++){
        int x,y,val;
        cin >> x >> y >> val;
        g[x].push_back(y);
        g[y].push_back(x);
        apple[x].push_back(val);
        apple[y].push_back(val);
    }
    dfs(1,0);
    cout << dp[1][q];
    return 0;
}