P2015 二叉苹果树

这道树形dp我又跪了。。


这道题给你二叉树,共有\(n-1\)条边,每条边有边权,只有在父亲结点被保留的情况下才能算进答案,求保留\(m\)条边的答案最大值。

我拿起来就开始写,后来才发现是边权啊!

翻题解发现,还是那个老思路:边权变为点权。只要把每一条边的边权弄到终点的点权即可。

由于是树,所以不会有一个点有多个边连入,所以放心地写。

状态方程还是那个dp[u][j] = std::max(dp[u][j], dp[u][j - k] + dp[v][k])

我们添加点权的时候在那个dp[u][1]里面加上去就好了。

其他都跟前面的是一样的。

我没用到这个二叉树的性质

代码:

#include<cstdio>
#include<algorithm>
const int maxn = 1005;
struct Edges
{
	int next, to;
} e[maxn];
int head[maxn], tot;
int dp[maxn][maxn];
int n, m;
int weight[maxn];
void link(int u, int v)
{
	e[++tot] = (Edges){head[u], v};
	head[u] = tot;
}
int dfs(int u)
{
	int ans = 1;
	for(int i = head[u]; i; i = e[i].next)
	{
		int v = e[i].to;
		int t = dfs(v);
		ans += t;
		for(int j = ans; j; j--)
		{
			for(int k = 1; k <= m; k++)
			{
				if(j - k > 0) dp[u][j] = std::max(dp[u][j], dp[u][j - k] + dp[v][k]);
			}
		}
	}
	return ans;
}
int main()
{
	scanf("%d%d", &n, &m);
	for(int i = 1; i < n; i++)
	{
		int u, v, w;
		scanf("%d%d%d", &u, &v, &w);
		link(u, v);
		dp[v][1] += w;
	}
	
	dfs(1);
	printf("%d\n", dp[1][m + 1]);
	return 0;
}
posted @ 2018-08-09 17:37  Garen-Wang  阅读(130)  评论(0编辑  收藏  举报