有一棵蘋果樹,如果樹枝有分叉,一定是分2叉(就是說沒有只有1個兒子的結點)
這棵樹共有n個結點(葉子點或者樹枝分叉點),編號為1-n,樹根編號一定是1。
我們用一根樹枝兩端連線的結點的編號來描述一根樹枝的位置。下面是一顆有4個樹枝的樹
2 5
\ /
3 4
\ /1
現在這顆樹枝條太多了,需要剪枝。但是一些樹枝上長有蘋果。
給定需要保留的樹枝數量,求出最多能留住多少蘋果。
輸入格式:
第1行2個數,n和q(1<=q<= n,1n表示樹的結點數,q表示要保留的樹枝數量。接下來n-1行描述樹枝的資訊。
每行3個整數,前兩個是它連線的結點的編號。第3個數是這根樹枝上蘋果的數量。
每根樹枝上的蘋果不超過30000個。
輸出格式:
乙個數,最多能留住的蘋果的數量。
輸入樣例#1: 複製
5 21 3 1
1 4 10
2 3 20
3 5 20
輸出樣例#1: 複製
21
/*這道題目好難啊!!!!!!!
我這個蒟蒻做了幾個小時也看不懂那個鬼狀態轉移
現在其實也只能略說一二 果然一本通的題目太難啦
(樹形dp)狀態轉移:f[u][j] = max(f[u][j],f[u][j-1-k]+f[v][k]+g[i].v)
真的很難理解:f[i][j]表示結點i保留j條樹枝時留住的蘋果的最大值
v是u的乙個兒子節點 那麼設乙個k 滿足 k<=j-1 表示以v為根的子樹保留的樹枝數 即上面的f[v][k]
f[u][j-1-k]表示的是除了根節點與v連得邊和剛剛的k條邊之外的最大蘋果數
記得還要加上這條邊的蘋果數 即g[i].v
然後呢那裡遍歷j和k時為什麼要逆序呢?其實和01揹包的道理差不多
順序推的話可能會造成重複計算
*/#include
using
namespace
std;
const
int maxn = 105
;int
head[maxn],n,q,size[maxn];
intf[maxn][maxn],cnt;
struct
nodeg[maxn*4
];void addedge(int
from,int to,int
v)void dfs1(int x,int
fa) }
}void dfs2(int x,int
fa) }
}}int
main()
dfs1(
1,0);
dfs2(
1,0);
printf("%d
",f[1
][q]);
return0;
}
洛谷 P2015 二叉蘋果樹
題目描述 有一棵蘋果樹,如果樹枝有分叉,一定是分2叉 就是說沒有只有1個兒子的結點 這棵樹共有n個結點 葉子點或者樹枝分叉點 編號為1 n,樹根編號一定是1。我們用一根樹枝兩端連線的結點的編號來描述一根樹枝的位置。下面是一顆有4個樹枝的樹 2 5 3 4 1 現在這顆樹枝條太多了,需要剪枝。但是一些...
洛谷P2015 二叉蘋果樹
有一棵蘋果樹,如果樹枝有分叉,一定是分2叉 就是說沒有只有1個兒子的結點 這棵樹共有n個結點 葉子點或者樹枝分叉點 編號為1 n,樹根編號一定是1。我們用一根樹枝兩端連線的結點的編號來描述一根樹枝的位置。下面是一顆有4個樹枝的樹 2 5 3 4 1 現在這顆樹枝條太多了,需要剪枝。但是一些樹枝上長有...
洛谷P2015 二叉蘋果樹
有一棵蘋果樹,如果樹枝有分叉,一定是分2叉 就是說沒有只有1個兒子的結點 這棵樹共有n個結點 葉子點或者樹枝分叉點 編號為1 n,樹根編號一定是1。我們用一根樹枝兩端連線的結點的編號來描述一根樹枝的位置。下面是一顆有4個樹枝的樹 2 5 3 4 1現在這顆樹枝條太多了,需要剪枝。但是一些樹枝上長有蘋...