洛谷P2015 二叉苹果树
题意:
给一棵二叉树,每条边有一个权值,去掉某些边之后,使剩下的二叉树边的权值之和最大
分析:
这是一个典型的树状DP题
状态转移方程: dp[k][u]=max(dp[k][u],dp[k][u−v]+dp[son][v−1]+val[k][i])
dp[k][u] 表示以编号为k的节点作为根节点的子树上留下来u条边时保留的最大苹果数
详解见注释中
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 110;
int dp[maxn][maxn];
int n, q;
bool vis[maxn] = {0}; //标记已经访问过的点
vector<int> edge[maxn], val[maxn]; //edge数组存边的情况,val数组存边的权值
int dfs(int k)
{
vis[k] = 1;
int cnt = 0; //cnt记录当前以k为根节点的子树所包含的节点数目
for (int i = 0; i < edge[k].size(); ++i)
{
int son = edge[k][i];
if (vis[son]) //已访问过的节点不再访问
continue;
cnt += dfs(son) + 1;
for (int u = min(cnt, q); u > 0; --u)
{
for (int v = min(u, q); v > 0; --v)
dp[k][u] = max(dp[k][u], dp[k][u - v] + dp[son][v - 1] + val[k][i]); //dp[k][u - v]表示以k为根节点的树上除去以son为根节点的子树后保留u-v条边所能保留的最大苹果数
//dp[son][v-1]表示以son为根节点的子树上保留v-1条边所能保留的最大苹果数
//u-(u-v)-(v-1)=1即k节点和son节点之间的边
//因为存入时edge和val相对应,所以val[k][i]即是节点k和son之间边的权值
}
}
return cnt;
}
int main(int argc, char const *argv[])
{
scanf("%d%d", &n, &q);
int u, v, x;
for (int i = 1; i < n; ++i)
{
scanf("%d%d%d", &u, &v, &x);
edge[u].push_back(v);
edge[v].push_back(u);
val[u].push_back(x);
val[v].push_back(x);
}
dfs(1);
printf("%d\n", dp[1][q]);
return 0;
}