【LUOGU P2014】选课(树形DP,多叉树转二叉树)

传送门

关于如何把多叉树转化为二叉树,有个口诀,叫做左儿子不变,右儿子兄♂弟。

详细的不多说,可以去参考一下相关资料。

等转化为二叉树了过后,让我们来琢磨一下。

左儿子:原根节点的孩子。

右儿子:原根节点的兄 ♂贵

也就是说,不能直接套用第一题的方程,但是可以对dp数组进行相同的定义。

对于一个根节点,都可以,选,或者,不选。

当给左儿子分配资源时,根节点必须选,而与右儿子无关。

因此,方程就显而易见了,dp[i][j]=max(dp[i][j],dp[i.rson][j],dp[i.lson][k]+dp[i.rson][j-k-1]+val[i]) (0<=k<j)

//dp[i][j]: i的所有兄弟和i的所有儿子 和i自己 学j门课的最大学分总和。
//dp[i][j]=max(dp[rson][j],dp[lson][k]+dp[rson][j-k-1]+val[i]) 
#include<bits/stdc++.h>
using namespace std;
const int N=305;
int n,m,bigson[N],dp[N][N];
 
struct node
{
    int val,lson,rson;
}tree[N*4];
int dfs(int now,int point)
{
    if(!now||!point)    return 0;
    if(dp[now][point])  return dp[now][point];
    dp[now][point]=dfs(tree[now].rson,point);
    for(int k=0;k<point;k++)
    {
        dp[now][point]=max(dp[now][point],dfs(tree[now].lson,k)+dfs(tree[now].rson,point-k-1)+tree[now].val);
    }
    return dp[now][point];
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        int k,s;    //爸爸 权值 
        cin>>k>>s;
        tree[i].val=s;
        if(bigson[k]==0)    tree[k].lson=i; //如果k还没有其他儿子 那么i就是儿子了
        else tree[bigson[k]].rson=i;
        bigson[k]=i; 
    }
    cout<<dfs(tree[0].lson,m);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值