树形背包

动态规划 树形背包

树形背包

树形背包的实现与普通01背包并无二样

eNVVHS.png

树形背包复杂度优化

当然,假如单纯是树形背包的话是不值得单独开一篇博客作记录的

尝试口胡分析一下复杂度:对于每一个节点,都要枚举其节点的子树大小次(第一层for);转移过程中,还需要遍历该节点的每一子树,并枚举其子树大小次(第二层次for),因此总复杂度为(O(n^3)).好像OI界里复杂度如此优秀的同时还上得了台面的只有同复杂度的floyd吧( ̄_ ̄|||)尝试进一步去优化流程

发现每一次遍历子树时,其实并不需要完整地枚举父节点的"完整"大小。想象一下,父节点是随着子节点的更新而不断扩大的

eNeVYQ.png

eNeb1s.png

eNuyhF.png

依次类推...更加通用的伪代码如下:

node u;
int size=0;
for(v=son of v){
    dfs(v);
    for(int i=0;i<=size;++i){
        for(int j=0;j<=sizeof(v);++j){
            f[i+j]=max(f[i]+f[j]+trans..)
        }
    }
    size+=sizeof(v);
}

再次尝试口胡证明一下复杂度:依旧是递归每一个节点,但是枚举次数被大大缩短(第一层for);利用子树进行更新的复杂度没变(第二层for)..因此..是(O(n^2))!(老师提出的结论就是这样的ㄟ( ▔, ▔ )ㄏ)

例题

CF 815C Karen and Supermarket

C. Karen and Supermarket

会发现将优惠序列连接起来会构成一棵树:

  1. 有n个节点和n-1条边
  2. 每一个节点只能向标号更小的节点连边,这一条性质保证了不会分裂成森林,也不会构成

令 f[i][j][0/1] 表示以i为根的子树中,购买 j 件物品的最小花费, 根节点(0/1)使用 / 不使用 优惠券。得到递推转移方程式如下:

[f[u][i+j][0]=min(f[u][i][0]+f[v][j][0])
]

[f[u][i+j][1]=min(f[u][i][1]+f[v][j][1])
]

[f[u][i+j][1]=min(f[u][i][1]+f[v][j][0])
]

倘若直接立方级的转移的话是tle的,加上小优化边dfs边dp即可ac。 (一遍ac祭φ(゜▽゜*)♪)

P3177 [HAOI2015]树上染色

P3177 [HAOI2015]树上染色

一个稍微复杂一点的树形背包。令f[i][j]表示以i为根节点的子树中有j个黑点。考虑每一条边对答案的贡献:

eNQFwq.png

得到状态转移方程:

[f[u][i+j]=max(f[u][i]+f[v][j]+边的贡献)
]

撒花★,°:.☆( ̄▽ ̄)/$:.°★

原文链接: https://www.cnblogs.com/ticmis/p/13210547.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    树形背包

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/360526

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 下午1:19
下一篇 2023年3月2日 下午1:20

相关推荐