版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhangjingyanzjyer/article/details/83069558
题目大意就是给你一棵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]);
}