题目:
给你一个 n 个节点的无向无根图,节点编号为 0 到 n - 1 。给你一个整数 n 和一个长度为 n - 1 的二维整数数组 edges ,其中 edges[i] = [ai, bi] 表示树中节点 ai 和 bi 之间有一条边。
每个节点都有一个价值。给你一个整数数组 price ,其中 price[i] 是第 i 个节点的价值。
一条路径的 价值和 是这条路径上所有节点的价值之和。
你可以选择树中任意一个节点作为根节点 root 。选择 root 为根的 开销 是以 root 为起点的所有路径中,价值和 最大的一条路径与最小的一条路径的差值。
请你返回所有节点作为根节点的选择中,最大 的 开销 为多少。
算法:
每个节点的价值为正数,所以价值和最大的路径和价值和最小的路径差值,问题转化为求路径去掉一个叶子节点之后的最大路径和。
遍历到一个节点node,对于node,我们统计包含叶子节点的最大路径价值和,和不包括叶子节点的最大路径和。求最大值。
当前在节点9,绿色路径是已经遍历过的,红色和黑色是未遍历的。最大价值和与最小价值和的差为:
1.红色路径减去叶子节点+绿色路径、或者绿色路径加上红色路径减去叶子节点。
2.不在当前路径上,要从9的父节点开始遍历。
func maxOutput(n int, edges [][]int, price []int) int64 {
// 建图
graph := make([][]int, n)
for i := range edges {
graph[edges[i][0]] = append(graph[edges[i][0]] , edges[i][1])
graph[edges[i][1]] = append(graph[edges[i][1]], edges[i][0])
}
ans := 0
// dfs(node, parent),返回从node开始的子树中,带叶子节点的最大价值和、不带叶子节点的最大价值和,
// 不失一般性,这里假设是从一个非根非叶子节点开始遍历的
var dfs func(node, parent int) (int, int)
dfs = func(node, parent int) (int, int) {
// 已遍历的路径中,包含所有节点和不包含叶子节点的最大路径和
allNodeCostMax := price[node]
// 如果当前是叶子节点,那么就不统计了
noLeafCostMax := 0
for _, neighbor := range graph[node] {
// 如果是叶子节点,这里就continue了,它只有一个父节点与它相连
if neighbor == parent {
continue
}
// 未遍历的路径上所有节点的最大路径和、以及不包含叶子节点的最大路径和
costAll, costNoLeaf := dfs(neighbor, node)
// 要么是已遍历的路径丢掉一个叶子节点,要么是未遍历的路径丢掉一个叶子节点
ans = max(ans, max(allNodeCostMax + costNoLeaf, noLeafCostMax + costAll))
allNodeCostMax = max(allNodeCostMax, costAll + price[node])
noLeafCostMax = max(noLeafCostMax, costNoLeaf + price[node])
}
return allNodeCostMax, noLeafCostMax
}
dfs(0, -1)
return int64(ans)
}
func max(a, b int) int {
if a > b {
return a
}
return b
}