E75【模板】树上背包 P2015 二叉苹果树

E75【模板】树上背包 P2015 二叉苹果树_哔哩哔哩_bilibili

 

E18【模板】树上背包 P2014 [CTSC1997] 选课 - 董晓 - 博客园

P2015 二叉苹果树 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

每条边选或不选,树上 01 背包

$f_{x,j}$ 表示 $x$ 子树上保留 $j$ 条边的最大数量
$$f_{x,j}=\max\limits_{j\in[m,1],k\in[0,j-1]}(f_{x,j-k-1}+f_{y,k}+w_i),w_i 为 (x,y) 的边权 $$

// 树上背包 O(n*m)
#include<bits/stdc++.h>
using namespace std;

#define N 105
vector<pair<int,int>>e[N];
int n,m,f[N][N],siz[N];

void dfs(int x,int fa){
  for(auto t:e[x]){
    int y=t.first,w=t.second;
    if(y==fa)continue;
    dfs(y,x);
    siz[x]+=siz[y]+1;
    for(int j=min(m,siz[x]);j;--j) //边数
      for(int k=min(j-1,siz[y]);k>=0;--k) //决策
        f[x][j]=max(f[x][j],f[x][j-k-1]+f[y][k]+w);
  }
}
int main(){
  scanf("%d%d",&n,&m);
  for(int i=1,x,y,w; i<n; ++i){
    scanf("%d%d%d",&x,&y,&w),
    e[x].push_back({y,w});
    e[y].push_back({x,w});
  }
  dfs(1,0);
  printf("%d\n",f[1][m]);
}

 

// 树上背包 O(n*m)
#include<bits/stdc++.h>
using namespace std;

#define N 105
vector<pair<int,int>>e[N];
int n,m,f[N][N];

void dfs(int x,int fa){
  for(auto t:e[x]){
    int y=t.first,w=t.second;
    if(y==fa) continue;
    for(int j=0;j<=m-1;j++) f[y][j]=f[x][j]+w;
    dfs(y,x);
    for(int j=1;j<=m;j++) f[x][j]=max(f[x][j],f[y][j-1]);
  }
}
int main(){
  scanf("%d%d",&n,&m);
  for(int i=1,x,y,w; i<n; ++i){
    scanf("%d%d%d",&x,&y,&w),
    e[x].push_back({y,w});
    e[y].push_back({x,w});
  }
  dfs(1,0);
  printf("%d\n",f[1][m]);
}

 

posted @ 2024-11-02 10:06  董晓  阅读(416)  评论(0)    收藏  举报