二叉苹果树(树形dp)
Posted loganacmer
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二叉苹果树(树形dp)相关的知识,希望对你有一定的参考价值。
二叉苹果树
题目描述
有一棵二叉苹果树,如果数字有分叉,一定是分两叉,即没有只有一个儿子的节点。这棵树共N个节点,标号1至N,树根编号一定为1。
我们用一根树枝两端连接的节点编号描述一根树枝的位置。一棵有四根树枝的苹果树,因为树枝太多了,需要剪枝。但是一些树枝上长有苹果,给定需要保留的树枝数量,求最多能留住多少苹果。
我们用一根树枝两端连接的节点编号描述一根树枝的位置。一棵有四根树枝的苹果树,因为树枝太多了,需要剪枝。但是一些树枝上长有苹果,给定需要保留的树枝数量,求最多能留住多少苹果。
输入描述:
第一行两个数N和Q,N表示树的节点数,Q表示要保留的树枝数量。
接下来N-1行描述树枝信息,每行三个整数,前两个是它连接的节点的编号,第三个数是这根树枝上苹果数量。
输出描述:
输出仅一行,表示最多能留住的苹果的数量。
示例1
输入
5 2 1 3 1 1 4 10 2 3 20 3 5 20
输出
21
备注:
对于100%的数据,1≤Q≤N≤100,N≠11,每根树枝上苹果不超过30000个。
题目思路:
f[i][j]表示以i为根节点的子树保留j根树枝的最多苹果数,d[i][j]表示i节点到j节点树枝上的苹果数。
vector作为邻接表记录与每个节点相邻的节点(注意dfs时不能走父节点)。
代码如下(记忆化搜索实现):
#include<bits/stdc++.h> #define ll long long using namespace std; int n,m,f[101][101],d[101][101]; vector<int> v[101]; int dfs(int x,int y,int fa) vector<int> child; int ans = 0; if(f[x][y]!=-1) return f[x][y]; if(x!=1&&v[x].size()==1||y==0) f[x][y] = ans; return ans; else if(v[x].size()==2&&x!=1||x==1&&v[x].size()==1) for(int i = 0;i<v[x].size();i++) if(v[x][i]!=fa) child.push_back(v[x][i]); ans = d[x][child[0]]+dfs(child[0],y-1,x); f[x][y] = ans; return ans; else for(int i = 0;i<v[x].size();i++) if(v[x][i]!=fa) child.push_back(v[x][i]); if(y>=2) for(int i = 0;i<y-1;i++) ans = max(ans,d[x][child[0]]+d[x][child[1]]+dfs(child[0],i,x)+dfs(child[1],y-i-2,x)); if(y>=1) ans = max(ans,d[x][child[0]]+dfs(child[0],y-1,x)); ans = max(ans,d[x][child[1]]+dfs(child[1],y-1,x)); f[x][y] = ans; return ans; int main() memset(d,-1,sizeof(d)); memset(f,-1,sizeof(f)); int a,b,c; cin>>n>>m; for(int i = 0;i<n-1;i++) cin>>a>>b>>c; v[a].push_back(b); v[b].push_back(a); d[a][b] = c; d[b][a] = c; cout<<dfs(1,m,0); return 0;
如果有错误的地方,还请各位大佬指正。
以上是关于二叉苹果树(树形dp)的主要内容,如果未能解决你的问题,请参考以下文章