DP - 樹形DP - 二叉蘋果樹
有一棵二叉蘋果樹,如果樹枝有分叉,一定是分兩叉,即沒有隻有一個兒子的節點。
這棵樹共 N 個節點,編號爲 1 至 N,樹根編號一定爲 1。
我們用一根樹枝兩端連接的節點編號描述一根樹枝的位置。
一棵蘋果樹的樹枝太多了,需要剪枝。但是一些樹枝上長有蘋果,給定需要保留的樹枝數量,求最多能留住多少蘋果。
這裏的保留是指最終與1號點連通。
輸入格式
第一行包含兩個整數 N 和 Q,分別表示樹的節點數以及要保留的樹枝數量。
接下來 N−1 行描述樹枝信息,每行三個整數,前兩個是它連接的節點的編號,第三個數是這根樹枝上蘋果數量。
輸出格式
輸出僅一行,表示最多能留住的蘋果的數量。
數據範圍
1≤Q<N≤100.
N≠1,
每根樹枝上蘋果不超過 30000 個。
輸入樣例:
5 2
1 3 1
1 4 10
2 3 20
3 5 20
輸出樣例:
21
分析:
說明:
代碼:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=110,M=2*N;
int n,m;
int e[M],ne[M],w[M],h[N],idx;
int f[N][N]; //f[i][j]:從以i爲根的子樹種,選j條邊的最大價值
void add(int a,int b,int c)
{
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
int dfs(int u,int fa)
{
for(int i=h[u];~i;i=ne[i])
{
int v=e[i];
if(v==fa) continue;
dfs(v,u);
for(int j=m;j;j--)
for(int k=0;k<j;k++)
f[u][j]=max(f[u][j],f[u][j-k-1]+f[v][k]+w[i]);
}
}
int main()
{
memset(h,-1,sizeof h);
cin>>n>>m;
for(int i=0;i<n-1;i++)
{
int a,b,c;
cin>>a>>b>>c;
add(a,b,c),add(b,a,c);
}
dfs(1,-1);
cout<<f[1][m]<<endl;
return 0;
}