2538. 最大价值和与最小价值和的差值

113 阅读2分钟

题目:
给你一个 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的父节点开始遍历。
图片.png

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
}