LOJ10153 二叉苹果树

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhangjingyanzjyer/article/details/83069558

https://loj.ac/problem/10153

题目大意就是给你一棵n个节点的带边权的树,让你留下q条边使留下的边的权值和最大。

这种题目显然有最优子结构的特征,所以可以使用树形dp来解决该问题。

f[i][j]表示以i为根的子树中保留j条边可以得到的最大价值

易推出f[i][j]=max(f[i][j],f[i][j-k-1]+f[v][k]+a[i])   (v为i的儿子 0≤k≤j-1)

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int n,q,cnt,nxt[2000],head[2000],to[2000],val[2000],f[2000][2000];
void add(int x,int y,int z)
{
	cnt++;nxt[cnt]=head[x];to[cnt]=y;val[cnt]=z;head[x]=cnt;
}
int dfs(int u,int fa)
{
	int ans=0;
	for (int i=head[u];i;i=nxt[i])
	{	
		int v=to[i];
		if (v==fa) continue;
		ans+=dfs(v,u)+1;//子树中的边数
		for (int j=min(ans,q);j;j--)
			for (int k=j-1;k>=0;k--)
				f[u][j]=max(f[u][j],f[u][j-k-1]+f[v][k]+val[i]);
	}
	return ans;
}
int main()
{
	int x,y,z;
	scanf("%d%d",&n,&q);
	for (int i=1;i<=n-1;i++)
	{	
		scanf("%d%d%d",&x,&y,&z);
		add(x,y,z);
		add(y,x,z);
	}
	dfs(1,0);
	printf("%d\n",f[1][q]);
}

猜你喜欢

转载自blog.csdn.net/zhangjingyanzjyer/article/details/83069558