洛谷 P2015 二叉苹果树

目录:


分析:

先上个动态转移方程:
f[a][j]=max(f[a][j],f[a][jk1]+f[to][k]+e[i].w)(1jmin(m,king[a]),0kmin(king[to],j1)) f [ a ] [ j ] = m a x ( f [ a ] [ j ] , f [ a ] [ j − k − 1 ] + f [ t o ] [ k ] + e [ i ] . w ) ( 1 ≤ j ≤ m i n ( m , k i n g [ a ] ) , 0 ≤ k ≤ m i n ( k i n g [ t o ] , j − 1 ) )
对于这个方程,内容是很好理解的,king代表以i点为根的树一共有几条边,a代表当前节点,to代表a的一个子节点,现在大家想想就理解了
但对于范围,小编就来解释解释:
j:j代表保留的枝数,因为我们输入时已经限制了最大保留数m,而树a一共只有king[a]条边,所以j肯定小于等于king[a]
k:k代表我们在子树to中砍掉了多少树枝,所以也肯定小于等于king[to],而至于j-1,是因为我们必须保留一个将to和a连接的边


代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define LL long long
using namespace std;
inline LL read() {
    LL d=0,f=1;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
    return d*f;
}
int n=read(),m=read();
int king[101],f[101][101],ls[101],x[101],c=0,w[101];
struct edg{
    int to,next,w;
}e[201];
void add(int a,int b,int www)
{
    e[c].to=b;e[c].w=www;e[c].next=ls[a];ls[a]=c++;
}
void dp(int a,int b)
{
    for(int i=ls[a];~i;i=e[i].next)
    {
        int to=e[i].to;
        if(to==b) continue;
        dp(to,a);
        king[a]+=king[to]+1;
        for(int j=min(m,king[a]);j>=1;--j)
          for(int k=min(king[to],j-1);k>=0;--k)
            f[a][j]=max(f[a][j],f[a][j-k-1]+f[to][k]+e[i].w);
    }
    return;
}
int main()
{     
    memset(ls,-1,sizeof ls);      
    int a,b,xw;
    for(int i=1;i<n;i++)
    {
        a=read();b=read();xw=read();
        add(a,b,xw);add(b,a,xw);
    }
    dp(1,0);
    printf("%d",f[1][m]);
    return 0;
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值