无向树节点值归零最优操作求解:我的BFS方法为何失效?
无向树节点值缩减操作的最小总成本求解
问题背景
给定一棵无向树和节点值数组val,每个节点i对应值val[i]。允许两种操作:
- 选择两个节点,将它们的值各减1,成本为两节点间的路径边数(距离);
- 选择同一节点,将其值减2,成本为0。
目标是将所有节点值减至0,求解最小总成本。
示例输入
t_from = [1, 1, 3, 3], t_to = [2, 3, 4, 5],val = [3, 2, 4, 2, 5]
(注:原输入的边5-5应为笔误,调整后符合示例中1到5距离为2的描述)
最优操作策略
先对单个节点执行无成本的减2操作:(1,1)、(2,2)、(3,3)两次、(4,4)、(5,5)两次,剩余节点值为[1,0,0,0,1];再选择(1,5)各减1,成本为2,最终总成本为2。
遇到的问题
尝试用BFS寻找奇数权重节点对并累加其距离,但该方法无效,求正确解法。
解决方案
核心观察
同一节点减2的操作成本为0,因此所有节点值的偶数部分可以完全无成本消除,我们只需要关注val[i]的奇偶性:
- 偶数节点:直接通过多次减2操作清零,无额外成本;
- 奇数节点:最终会剩余1,必须与另一个奇数节点配对,通过跨节点减1操作消除(每次跨节点操作可消除两个奇数)。
注意:树中奇数节点的数量必为偶数,否则无法完全清零(题目默认存在可行解)。
为什么BFS配对思路行不通
直接两两配对奇数节点并累加距离的方式,会重复计算路径上的边。例如当多个奇数节点分布在树的不同分支时,错误的配对会导致部分边被多次经过,而最优策略需要让每条边的总经过次数最少,因此该方法无法得到最小成本。
正确解法:统计每条边的贡献
最小总成本等于所有边在必要配对路径中被经过的总次数(每条边经过一次对应1单位成本),具体步骤如下:
- 筛选奇数节点:遍历节点数组,标记出
val[i]为奇数的节点,记总数量为k(k为偶数)。 - 树形DP计算边的贡献:
- 任选一个节点作为根(如节点1),对树进行后序遍历;
- 对每个节点
u,统计其子树内的奇数节点数量cnt[u]; - 对于
u与其父节点p之间的边,该边的贡献为cnt[u] × (k - cnt[u])——子树内有cnt[u]个奇数,子树外有k - cnt[u]个奇数,每一对跨子树的奇数节点配对都会经过这条边一次。
- 累加所有边的贡献:将每条边的贡献相加,结果即为最小总成本。
示例验证
示例中奇数节点为1和5(共2个):
- 以1为根遍历:
- 节点2的子树:0个奇数,边1-2贡献
0×2=0; - 节点3的子树:包含节点5(奇数),
cnt[3]=1,边1-3贡献1×(2-1)=1; - 节点4的子树:0个奇数,边3-4贡献
0×2=0; - 节点5的子树:1个奇数,边3-5贡献
1×(2-1)=1;
- 节点2的子树:0个奇数,边1-2贡献
- 总贡献为
0+1+0+1=2,与示例的最优总成本一致。
实现提示
- 用邻接表存储树结构,遍历过程中跳过父节点避免重复访问;
- 后序遍历过程中维护子树的奇数节点计数;
- 每条边仅计算一次,避免重复累加。
内容的提问来源于stack exchange,提问作者Utsav Patel
相关产品推荐
相关产品推荐

