1074. 二叉蘋果樹(有依賴的揹包問題)

1074. 二叉蘋果樹

有一棵二叉蘋果樹,如果樹枝有分叉,一定是分兩叉,即沒有隻有一個兒子的節點。

這棵樹共 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

分析:這是一道有依賴的揹包問題,如果要選擇當前節點,則必須選擇它的父節點

有一點需要注意,在決策那一層的循環中,k只能小於揹包體積j,因爲x選y的時候也需要選擇一條邊,原本x取了k條邊,加上多的,就是k+1條邊,所以x選j條邊,則需要再選擇j-(k+1)條邊,即j-k-1

#include <iostream>
#include <algorithm>
using namespace std;
const int N = 110;
int n,m,tot;
int head[N],nexts[N*2],ver[N*2],edge[N*2];
int f[N][N];
void add(int x,int y,int z){
    ver[++tot]=y,edge[tot]=z;
    nexts[tot]=head[x],head[x]=tot;
}
void dp(int x,int father){
    for(int i=head[x];i;i=nexts[i]){//物品組
        int y=ver[i],z=edge[i];
        if(y==father) continue;
        dp(y,x);
        for(int j=m;j>=0;j--){//體積
            for(int k=0;k<j;k++){//決策
                f[x][j]=max(f[x][j],f[x][j-1-k]+f[y][k]+z);
            }
        }
    }

}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=0;i<n-1;i++){
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        add(a,b,c),add(b,a,c);
    }
    dp(1,0);
    printf("%d",f[1][m]);
    return 0;
}

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章