[题解]P2015 二叉苹果树
树形dp,一般用dfs辅助解决。
当我们搜索到\(u\),此时剩下\(cnt\)条边可以用,也就是说\(u\)为根节点的子树最多可以保留\(cnt\)条边。
由于上一层的需求,我们显然需要枚举剩余边数\(i\)(\(1\leq i\leq cnt\))。接下来对于每个\(i\),我们考虑剩余的\(u\)条边可以怎么放。
- 只分配给左边,那么连接左子树用去\(1\)条边,左子树实际有\(i-1\)条边可以用。
- 只分配给右边,那么连接右子树用去\(1\)条边,右子树实际有\(i-1\)条边可以用。
- 两边都分配,枚举左子树分配多少条边,用\(j\)表示,那么连接左右子树用去\(2\)条边,右子树实际有\(i-j-2\)条边可以用(\(0\leq j\leq i-2\))。你可能会疑惑,\(j=0\)也算分配给左子树吗?因为我们已经拿出\(2\)条边来连接左右子树了,所以尽管左子树没有边可用,这与第②条也是不一样的。
边界条件就是叶子节点,搜索到就直接结束。
点击查看代码
#include<bits/stdc++.h> using namespace std; struct edge{ int to,w; }; vector<edge> G[110]; int f[110][110],n,q; bool vis[110]; void dfs(int pos,int cnt){ if(G[pos].size()==1) return; int ch[2],w[2],len=0; for(auto i:G[pos]){//计算左右子节点以及权值 if(!vis[i.to]){ w[len]=i.w; ch[len++]=i.to; } } vis[pos]=1; dfs(ch[0],cnt-1); dfs(ch[1],cnt-1); for(int i=1;i<=cnt;i++){ f[pos][i]=max(f[ch[1]][i-1]+w[1],f[ch[0]][i-1]+w[0]); for(int j=0;j<=i-2;j++){ f[pos][i]=max(f[pos][i],f[ch[0]][j]+w[0]+f[ch[1]][i-j-2]+w[1]); } } vis[pos]=0; } int main(){ cin>>n>>q; for(int i=1;i<n;i++){ int u,v; edge e; cin>>u>>v>>e.w; e.to=v,G[u].push_back(e); e.to=u,G[v].push_back(e); } dfs(1,q); cout<<f[1][q]; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效