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]); }
浙公网安备 33010602011771号