洛谷P2015 二叉蘋果樹
阿新 • • 發佈:2018-11-09
題面:
有一棵蘋果樹,如果樹枝有分叉,一定是分2叉(就是說沒有隻有1個兒子的結點)
這棵樹共有N個結點(葉子點或者樹枝分叉點),編號為1-N,樹根編號一定是1。
我們用一根樹枝兩端連線的結點的編號來描述一根樹枝的位置。下面是一顆有4個樹枝的樹
2 5
\ /
3 4
\ /
1
現在這顆樹枝條太多了,需要剪枝。但是一些樹枝上長有蘋果。
給定需要保留的樹枝數量,求出最多能留住多少蘋果。
輸入輸出格式
輸入格式:
第1行2個數, 和 。
N表示樹的結點數,Q表示要保留的樹枝數量。接下來 行描述樹枝的資訊。
每行3個整數,前兩個是它連線的結點的編號。第3個數是這根樹枝上蘋果的數量。
每根樹枝上的蘋果不超過30000個。
輸出格式:
一個數,最多能留住的蘋果的數量。
輸入輸出樣例
輸入樣例
5 2
1 3 1
1 4 10
2 3 20
3 5 20
輸出樣例
21
分析:
表⽰以i節點為根,保留j個樹枝最多留下
多少個蘋果。
只給左⼉⼦:
只給右⼉⼦:
都分⼀點:
.
另種思路在程式碼中說明
code:(搜尋+dp)
#include<cstdio>
#include<cmath>
using namespace std;
int n,q;
struct ben
{
int to,last,val,dq;//to記錄這條邊的終點,last記錄上一條邊,dq記錄邊的起點,val記錄邊的權值
}a[205];
int f[205][205];
int cnt=1;
int head[205];//head[i]表示以i為起點的邊的編號
void add(int x,int y,int num)//連邊函式
{
a[cnt].to=y;
a[cnt].last=head[x];
a[cnt].dq=x;
a[cnt].val=num;
head[x]=cnt;
cnt++;
}
void search(int dq,int father)
{
for(int i=head[dq];i!=-1;i=a[i].last)
{
int b=a[i].to;//找到這條邊的終點
if(b==father)continue;//不能為起點
f[b][1]=a[i].val;//初始化
search(b,dq);//搜尋
for(int j=q;j>=1;j--)
{
for(int k=0;k<=j;k++)
{
if((j!=1&&j!=k)||dq==1)
{
f[dq][j]=fmax(f[dq][j],f[b][k]+f[dq][j-k]);//列舉中間點k,得出方程
}
}
}
}
}
int main()
{
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
{
head[i]=-1;
}//初始化
for(int i=1;i<n;i++)
{
int x,y,num;
scanf("%d%d%d",&x,&y,&num);
add(x,y,num);
add(y,x,num);//注意要連雙向邊
}
search(1,0);
printf("%d",f[1][q]);
return 0;
}