URAL 1018 二叉苹果树(简单树形dp)

题目:http://acm.timus.ru/problem.aspx?space=1&num=1018
题意:

有一棵苹果树,苹果树的是一棵二叉树,共N个节点,树节点编号为1~N,编号为1的节点为树根,边可理解为树的分枝,每个分支都长着若干个苹果,现在要要求减去若干个分支,保留M个分支,要求这M个分支的苹果数量最多。

分析:

简单的树形dp:
d[u][q]表示以u为根的子树保留q个树枝可以得到的最多的苹果数。
状态转移也是比较显然的:是每个子树单独选一个路线还是两条路线都选。
还看到有人用的是背包的思想,其实都一样。
(提醒自己:不过这题需要注意的怎么区别一个点的两个子结点和父结点,刚开始用了临时变量,在递归的时候被改了,调试了很久才发现问题,然后改成全局变量就好了,1A。)

代码:

using namespace std;
typedef long long ll;
typedef pair<int,int>pii;
const int N = 100 + 9;
int d[N][N];
vector<pii>g[N],a[N];

int dfs(int u,int f,int q)
{
    int& ans=d[u][q];
    if(ans>=0)return ans;
    ans=0;
    if(q<=0)return ans;

    for(int i=0;i<g[u].size();i++){
        int v=g[u][i].first;
        int w=g[u][i].second;
        if(v==f)continue;
        a[u].push_back(g[u][i]);
        for(int j=0;j<q;j++)
            dfs(v,u,j);
        ans=max(ans,d[v][q-1]+w);
    }
    if(a[u].size()>=2)
    for(int j=0;j<=q-2;j++){
        int t=d[a[u][0].first][j]+d[a[u][1].first][q-j-2]+a[u][0].second+a[u][1].second;
        ans=max(t,ans);
    }

    return ans;
}
int main() {
    //freopen("f.txt","r",stdin);
    int n,k,u,v,w;
    memset(d,-1,sizeof(d));
    scanf("%d%d",&n,&k);
    for(int i=0;i<n-1;i++){
        scanf("%d%d%d",&u,&v,&w);
        g[u].push_back(pii(v,w));
        g[v].push_back(pii(u,w));
    }
    dfs(1,-1,k);
    printf("%d\n",d[1][k]);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值