给你一个 n
个节点的无向无根图,节点编号为 0
到 n - 1
。给你一个整数 n
和一个长度为 n - 1
的二维整数数组 edges
,其中 edges[i] = [ai, bi]
表示树中节点 ai
和 bi
之间有一条边。
每个节点都有一个价值。给你一个整数数组 price
,其中 price[i]
是第 i
个节点的价值。
一条路径的 价值和 是这条路径上所有节点的价值之和。
你可以选择树中任意一个节点作为根节点 root
。选择 root
为根的 开销 是以 root
为起点的所有路径中,价值和 最大的一条路径与最小的一条路径的差值。
请你返回所有节点作为根节点的选择中,最大 的 开销 为多少。
示例 1:
输入:n = 6, edges = [[0,1],[1,2],[1,3],[3,4],[3,5]], price = [9,8,7,6,10,5] 输出:24 解释:上图展示了以节点 2 为根的树。左图(红色的节点)是最大价值和路径,右图(蓝色的节点)是最小价值和路径。 - 第一条路径节点为 [2,1,3,4]:价值为 [7,8,6,10] ,价值和为 31 。 - 第二条路径节点为 [2] ,价值为 [7] 。 最大路径和与最小路径和的差值为 24 。24 是所有方案中的最大开销。
示例 2:
输入:n = 3, edges = [[0,1],[1,2]], price = [1,1,1] 输出:2 解释:上图展示了以节点 0 为根的树。左图(红色的节点)是最大价值和路径,右图(蓝色的节点)是最小价值和路径。 - 第一条路径包含节点 [0,1,2]:价值为 [1,1,1] ,价值和为 3 。 - 第二条路径节点为 [0] ,价值为 [1] 。 最大路径和与最小路径和的差值为 2 。2 是所有方案中的最大开销。
提示:
1 <= n <= 105
edges.length == n - 1
0 <= ai, bi <= n - 1
edges
表示一棵符合题面要求的树。price.length == n
1 <= price[i] <= 105
方法一:树形 DP
由于每个节点价值均为正整数,因此,以节点
我们设计一个函数
函数
初始化
对于节点
- 前面不去掉端点的最大路径和加上当前节点去掉端点的最大路径和,即
$a + d$ ; - 前面去掉端点的最大路径和加上当前节点不去掉端点的最大路径和,即
$b + c$ 。
我们更新答案的最大值,即
然后更新
时间复杂度为
class Solution:
def maxOutput(self, n: int, edges: List[List[int]], price: List[int]) -> int:
def dfs(i, fa):
a, b = price[i], 0
for j in g[i]:
if j != fa:
c, d = dfs(j, i)
nonlocal ans
ans = max(ans, a + d, b + c)
a = max(a, price[i] + c)
b = max(b, price[i] + d)
return a, b
g = defaultdict(list)
for a, b in edges:
g[a].append(b)
g[b].append(a)
ans = 0
dfs(0, -1)
return ans
class Solution {
private List<Integer>[] g;
private long ans;
private int[] price;
public long maxOutput(int n, int[][] edges, int[] price) {
g = new List[n];
Arrays.setAll(g, k -> new ArrayList<>());
for (var e : edges) {
int a = e[0], b = e[1];
g[a].add(b);
g[b].add(a);
}
this.price = price;
dfs(0, -1);
return ans;
}
private long[] dfs(int i, int fa) {
long a = price[i], b = 0;
for (int j : g[i]) {
if (j != fa) {
var e = dfs(j, i);
long c = e[0], d = e[1];
ans = Math.max(ans, Math.max(a + d, b + c));
a = Math.max(a, price[i] + c);
b = Math.max(b, price[i] + d);
}
}
return new long[] {a, b};
}
}
class Solution {
public:
long long maxOutput(int n, vector<vector<int>>& edges, vector<int>& price) {
vector<vector<int>> g(n);
for (auto& e : edges) {
int a = e[0], b = e[1];
g[a].push_back(b);
g[b].push_back(a);
}
using ll = long long;
using pll = pair<ll, ll>;
ll ans = 0;
function<pll(int, int)> dfs = [&](int i, int fa) {
ll a = price[i], b = 0;
for (int j : g[i]) {
if (j != fa) {
auto [c, d] = dfs(j, i);
ans = max({ans, a + d, b + c});
a = max(a, price[i] + c);
b = max(b, price[i] + d);
}
}
return pll{a, b};
};
dfs(0, -1);
return ans;
}
};
func maxOutput(n int, edges [][]int, price []int) int64 {
g := make([][]int, n)
for _, e := range edges {
a, b := e[0], e[1]
g[a] = append(g[a], b)
g[b] = append(g[b], a)
}
type pair struct{ a, b int }
ans := 0
var dfs func(i, fa int) pair
dfs = func(i, fa int) pair {
a, b := price[i], 0
for _, j := range g[i] {
if j != fa {
e := dfs(j, i)
c, d := e.a, e.b
ans = max(ans, max(a+d, b+c))
a = max(a, price[i]+c)
b = max(b, price[i]+d)
}
}
return pair{a, b}
}
dfs(0, -1)
return int64(ans)
}
func max(a, b int) int {
if a > b {
return a
}
return b
}