Difference Between Maximum and Minimum Price Sum

Difference Between Maximum and Minimum Price Sum

There exists an undirected and initially unrooted tree with $n$ nodes indexed from $0$ to $n - 1$. You are given the integer $n$ and a 2D integer array edges of length $n - 1$, where edges[i] = [ai, bi] indicates that there is an edge between nodes ai and bi in the tree.

Each node has an associated price. You are given an integer array price, where price[i] is the price of the ith node.

The price sum of a given path is the sum of the prices of all nodes lying on that path.

The tree can be rooted at any node root of your choice. The incurred cost after choosing root is the difference between the maximum and minimum price sum amongst all paths starting at root.

Return the maximum possible cost amongst all possible root choices.

Example 1:

Input: n = 6, edges = [[0,1],[1,2],[1,3],[3,4],[3,5]], price = [9,8,7,6,10,5]
Output: 24
Explanation: The diagram above denotes the tree after rooting it at node 2. The first part (colored in red) shows the path with the maximum price sum. The second part (colored in blue) shows the path with the minimum price sum.
- The first path contains nodes [2,1,3,4]: the prices are [7,8,6,10], and the sum of the prices is 31.
- The second path contains the node [2] with the price [7].
The difference between the maximum and minimum price sum is 24. It can be proved that 24 is the maximum cost.

Example 2:

Input: n = 3, edges = [[0,1],[1,2]], price = [1,1,1]
Output: 2
Explanation: The diagram above denotes the tree after rooting it at node 0. The first part (colored in red) shows the path with the maximum price sum. The second part (colored in blue) shows the path with the minimum price sum.
- The first path contains nodes [0,1,2]: the prices are [1,1,1], and the sum of the prices is 3.
- The second path contains node [0] with a price [1].
The difference between the maximum and minimum price sum is 2. It can be proved that 2 is the maximum cost.

Constraints:

  • $1 \leq n \leq {10}^5$
  • $\text{edges.length} \mathrm{ \ == \ } n - 1$
  • $0 \leq a_i, b_i \leq n - 1$
  • $\text{edges represents a valid tree}$.
  • $\text{price.length} \mathrm{ \ == \ } n$
  • $1 \leq \text{price}[i] \leq {10}^5$

 

解题思路

  由于每个节点的权值都是正整数,因此最短路径必然就只有根节点这个节点,朴素做法就是枚举每个点作为根节点然后dfs求最长路径,然后再减去根节点的权值,时间复杂度为$O(n^2)$。

  正解是树形dp,与求树的直径几乎一样,不过后面算答案的时候会有些变化。由于是求树的最长路径,因此这条最长路径的两个端点必然是度数为$1$的端点(这里的$1$个度数指该节点要么只有父节点,要么只有一个子节点。否则还可以继续往其他节点走,路径权值会变大,矛盾),因此这个树的最长路径就是树的直径,而树的直径可以通过树形dp来求解,时间复杂度为$O(n)$。

  在求完两边dfs后会得到每个节点的$d1[i]$和$up[i]$,其中$d1[i]$表示以节点$i$为根的子树的最长路径,$up[i]$表示从节点$i$向其父节点走的最长路径。由于答案是最长路径减去一个端点的值,这个端点必然是度数为$1$的节点,因此在枚举时只计算度数为$1$的节点,如果节点$i$的度数为$1$,那么以$i$为端点要求的路径权值就是$\max(d1[i], up[i]) - w[i]$。

  AC代码如下:

 1 class Solution {
 2 public:
 3     long long maxOutput(int n, vector<vector<int>>& edges, vector<int>& price) {
 4         vector<vector<int>> g(n);
 5         for (auto &p : edges) {
 6             g[p[0]].push_back(p[1]);
 7             g[p[1]].push_back(p[0]);
 8         }
 9         vector<long long> d1(n), d2(n), son(n, -1), up(n);
10         function<void(int, int)> dfs_d = [&](int u, int pre) {
11             d1[u] = price[u];
12             for (auto &i : g[u]) {
13                 if (i != pre) {
14                     dfs_d(i, u);
15                     int d = d1[i] + price[u];
16                     if (d >= d1[u]) d2[u] = d1[u], d1[u] = d, son[u] = i;
17                     else if (d > d2[u]) d2[u] = d;
18                 }
19             }
20         };
21         function<void(int, int)> dfs_up = [&](int u, int pre) {
22             up[u] += price[u];
23             for (auto &i : g[u]) {
24                 if (i != pre) {
25                     if (son[u] != i) up[i] += max(up[u], d1[u]);
26                     else up[i] += max(up[u], d2[u]);
27                     dfs_up(i, u);
28                 }
29             }
30         };
31         dfs_d(0, -1);
32         dfs_up(0, -1);
33         long long ret = 0;
34         for (int i = 0; i < n; i++) {
35             if (g[i].size() == 1) ret = max(ret, max(d1[i], up[i]) - price[i]);
36         }
37         return ret;
38     }
39 };

 

参考资料

  二维差分模板 双指针 树形DP【力扣周赛 328】:https://www.bilibili.com/video/BV1QT41127kJ/

posted @ 2023-01-18 12:15  onlyblues  阅读(31)  评论(0编辑  收藏  举报
Web Analytics