树形DP3【2024蓝桥杯0基础】-学习笔记

路径相关树形DP

学习内容

树上路径1

例题分析

在这里插入图片描述
先以树形DP的形式求出以某一个点为根的时候的答案(一般都是以1为根的时候),然后再进行一次自上而下的DFS计算答案。
也就是说,分两步,1.树形DP2.在进行第二次DFS时,两个点之间的关系。
首先,
如果我们假设某个节点为根,将无根树化为有根树,在搜索回溯时统计子树的深度和,则可以用一次搜索算出以该节点为根时的深度和,其时间复杂度为O(n)。如果我们每个点都这么求,则n^2
在这里插入图片描述

状态变化

这里的ans[u]表示以u为根节点的路径权重和,siz[v]表示以v为根节点的子树的节点个数:
ans[u]= ans[u]- siz[v]+(siz[1]- siz[v])

代码复现
from collections import defaultdict


def dfs(u, dep, fa):  # 传入当前节点u,深度,父节点
    global sum_depth
    sum_depth += dep  # 加上当前节点u的深度
    # 遍历u的所有子节点
    for v in e[u]:
        if v == fa:
            continue
        dfs(v, dep + 1, u)  # 遍历到子节点
        siz[u] += siz[v]  # 通过这一步,可以统计u所有子节点数


def dfs2(u, fa):  # 用来跟新其余节点为根的解
    for v in e[u]:
        if v == fa:
            continue
        # dp[v] = dp[u] - siz[v] + (n - siz[v])
        dp[v] = dp[u] - 2 * siz[v] + n  # 当前节点v的解=左边变化值+右边变化值
        dfs2(v, u)


n = int(input())
dp = [0] * (n + 1)  # 用来更新不同节点为根时的深度和
siz = [1] * (n + 1)  # 以i为根节点,其左子树的节点数,初始值为1表示仅包含该节点
# 建树
e = defaultdict(list)
for _ in range(n - 1):
    u, v = map(int, input().split())
    e[u].append(v)
    e[v].append(u)
# 第一遍dfs,找到以1为根节点的深度和
sum_depth = 0  # 用来记录深度和
dfs(1, 0, 0)
# 第二遍dfs,求出其余点作为根的答案
dp[1] = sum_depth  # 6
dfs2(1, 0)  # dp=[0, 6, 5, 9, 8, 8]
print(max(dp))

树上路径2

题目分析

在这里插入图片描述

状态分析

在这里插入图片描述

感悟

我们可以看出换根DP的套路:(重点是分析子树与原来的状态变化)
指定某个节点为根节点。
1,第一次搜索完成预处理(如子树大小等),同时得到该节点的解
2,第二次搜索进行换根的动态规划,由已知解的节点推出相连节点的解。

蓝桥杯云课学习笔记分享,欢迎大佬们批评指正!

一直在进步就好咯!

by 闻不多

  • 10
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值