题目大意:

一颗苹果树上,每条边都对应了一个权值,最后留下包括root : 1在的含有 m 条边的子树 , 希望留下的子树中权值之和最大

这里保留m条边,我们可以看作是保留了 m + 1 个点

令dp[u][j] 表示 u 为根的子树中包含了j个点的子树中得到的权值最大和

状态转移方程:

dp[u][j] = max{dp[v][k] + dp[u][j-k] + e[i].d} v为u的子节点 j>k>=1 ,  1<=j<=m+1

 #include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int N = ;
int val[N] , first[N] , k , dp[N][N]; struct Edge{
int y , next , d;
}e[N<<]; void add_edge(int x, int y , int d)
{
e[k].y = y , e[k].d = d , e[k].next = first[x];
first[x] = k++;
} void dfs(int u , int fa , int m)
{
for(int i = first[u] ; i!=- ; i=e[i].next){
int v = e[i].y;
if(v == fa) continue;
dfs(v , u , m);
for(int j = m ;j>=; j--)
for(int k= ; k<j ; k++)
dp[u][j] = max(dp[u][j] , dp[v][k] + dp[u][j-k] + e[i].d);
}
} int main()
{
// freopen("a.in" , "r" , stdin);
int n,m,x,y,d;
while(scanf("%d%d" , &n , &m)==)
{
memset(first , - , sizeof(first));
k = ;
for(int i= ; i<n ; i++){
scanf("%d%d%d" , &x , &y , &d);
add_edge(x , y , d);
add_edge(y , x , d);
} memset(dp , , sizeof(dp));
dfs( , - , m+); printf("%d\n" , dp[][m+]);
}
return ;
}
05-11 21:45
查看更多