/*
QUESTION 12: Media.Net OA — Choosing the Most Valuable Tree Root
Problem Statement:
You are given a tree.
Each node contains a candy value.
If you choose some node as the root, then every root-to-leaf path has a path sum.
For that chosen root:
best = maximum root-to-leaf path sum
worst = minimum root-to-leaf path sum
The value of the root is:
best - worst
Return the maximum value among all possible roots.
Hard Constraints:
1 <= N <= 200000
1 <= candy[i] <= 1e9
Example:
candies = [6, 2, 9, 1]
edges:
1 - 2
2 - 3
2 - 4
Expected Output:
8
Explanation:
If node 2 is chosen as root:
paths are:
2 -> 1 = 8
2 -> 3 = 11
2 -> 4 = 3
best - worst = 11 - 3 = 8
Brute Force:
For every node:
- Treat it as root.
- DFS to all leaves.
- Find max and min root-to-leaf path sums.
Time Complexity:
O(N^2)
Optimized Approach:
Use rerooting DP.
For each directed side of an edge, compute the best and worst path from that side
to a leaf in that component.
Then every node can combine values from all neighboring directions.
Time Complexity:
O(N)
Space Complexity:
O(N)
*/
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
using ll = long long;
const ll NEG = -(1LL << 60);
const ll POS = (1LL << 60);
int n;
vector<vector<int>> g;
vector<ll> val;
vector<ll> downMax, downMin;
ll answer = 0;
void dfsDown(int u, int p) {
downMax[u] = NEG;
downMin[u] = POS;
bool hasChild = false;
for (int v : g[u]) {
if (v == p) continue;
hasChild = true;
dfsDown(v, u);
downMax[u] = max(downMax[u], val[u] + downMax[v]);
downMin[u] = min(downMin[u], val[u] + downMin[v]);
}
if (!hasChild) {
downMax[u] = val[u];
downMin[u] = val[u];
}
}
void dfsReroot(int u, int p, ll fromParentMax, ll fromParentMin) {
vector<pair<ll, int>> maxCand;
vector<pair<ll, int>> minCand;
if (fromParentMax != NEG) {
maxCand.push_back({fromParentMax, p});
minCand.push_back({fromParentMin, p});
}
for (int v : g[u]) {
if (v == p) continue;
maxCand.push_back({downMax[v], v});
minCand.push_back({downMin[v], v});
}
if (!maxCand.empty()) {
ll rootMax = val[u] + max_element(maxCand.begin(), maxCand.end())->first;
ll rootMin = val[u] + min_element(minCand.begin(), minCand.end())->first;
answer = max(answer, rootMax - rootMin);
}
for (int v : g[u]) {
if (v == p) continue;
ll bestMax = NEG;
ll bestMin = POS;
for (auto [x, id] : maxCand) {
if (id != v) bestMax = max(bestMax, x);
}
for (auto [x, id] : minCand) {
if (id != v) bestMin = min(bestMin, x);
}
ll passMax = (bestMax == NEG ? val[u] : val[u] + bestMax);
ll passMin = (bestMin == POS ? val[u] : val[u] + bestMin);
dfsReroot(v, u, passMax, passMin);
}
}
long long bestRootValue(vector<int>& candies, vector<vector<int>>& edges) {
n = candies.size();
if (n == 1) return 0;
val.assign(n, 0);
for (int i = 0; i < n; i++) {
val[i] = candies[i];
}
g.assign(n, {});
for (auto &e : edges) {
int u = e[0] - 1;
int v = e[1] - 1;
g[u].push_back(v);
g[v].push_back(u);
}
downMax.assign(n, NEG);
downMin.assign(n, POS);
dfsDown(0, -1);
dfsReroot(0, -1, NEG, POS);
return answer;
}
};
int main() {
Solution sol;
vector<int> candies = {6, 2, 9, 1};
vector<vector<int>> edges = {
{1, 2},
{2, 3},
{2, 4}
};
cout << sol.bestRootValue(candies, edges) << endl;
return 0;
}
LyoKUVVFU1RJT04gMTI6IE1lZGlhLk5ldCBPQSDigJQgQ2hvb3NpbmcgdGhlIE1vc3QgVmFsdWFibGUgVHJlZSBSb290CgpQcm9ibGVtIFN0YXRlbWVudDoKWW91IGFyZSBnaXZlbiBhIHRyZWUuCkVhY2ggbm9kZSBjb250YWlucyBhIGNhbmR5IHZhbHVlLgoKSWYgeW91IGNob29zZSBzb21lIG5vZGUgYXMgdGhlIHJvb3QsIHRoZW4gZXZlcnkgcm9vdC10by1sZWFmIHBhdGggaGFzIGEgcGF0aCBzdW0uCgpGb3IgdGhhdCBjaG9zZW4gcm9vdDoKYmVzdCA9IG1heGltdW0gcm9vdC10by1sZWFmIHBhdGggc3VtCndvcnN0ID0gbWluaW11bSByb290LXRvLWxlYWYgcGF0aCBzdW0KClRoZSB2YWx1ZSBvZiB0aGUgcm9vdCBpczoKYmVzdCAtIHdvcnN0CgpSZXR1cm4gdGhlIG1heGltdW0gdmFsdWUgYW1vbmcgYWxsIHBvc3NpYmxlIHJvb3RzLgoKSGFyZCBDb25zdHJhaW50czoKMSA8PSBOIDw9IDIwMDAwMAoxIDw9IGNhbmR5W2ldIDw9IDFlOQoKRXhhbXBsZToKY2FuZGllcyA9IFs2LCAyLCA5LCAxXQplZGdlczoKMSAtIDIKMiAtIDMKMiAtIDQKCkV4cGVjdGVkIE91dHB1dDoKOAoKRXhwbGFuYXRpb246CklmIG5vZGUgMiBpcyBjaG9zZW4gYXMgcm9vdDoKcGF0aHMgYXJlOgoyIC0+IDEgPSA4CjIgLT4gMyA9IDExCjIgLT4gNCA9IDMKCmJlc3QgLSB3b3JzdCA9IDExIC0gMyA9IDgKCkJydXRlIEZvcmNlOgpGb3IgZXZlcnkgbm9kZToKLSBUcmVhdCBpdCBhcyByb290LgotIERGUyB0byBhbGwgbGVhdmVzLgotIEZpbmQgbWF4IGFuZCBtaW4gcm9vdC10by1sZWFmIHBhdGggc3Vtcy4KClRpbWUgQ29tcGxleGl0eToKTyhOXjIpCgpPcHRpbWl6ZWQgQXBwcm9hY2g6ClVzZSByZXJvb3RpbmcgRFAuCgpGb3IgZWFjaCBkaXJlY3RlZCBzaWRlIG9mIGFuIGVkZ2UsIGNvbXB1dGUgdGhlIGJlc3QgYW5kIHdvcnN0IHBhdGggZnJvbSB0aGF0IHNpZGUKdG8gYSBsZWFmIGluIHRoYXQgY29tcG9uZW50LgoKVGhlbiBldmVyeSBub2RlIGNhbiBjb21iaW5lIHZhbHVlcyBmcm9tIGFsbCBuZWlnaGJvcmluZyBkaXJlY3Rpb25zLgoKVGltZSBDb21wbGV4aXR5OgpPKE4pCgpTcGFjZSBDb21wbGV4aXR5OgpPKE4pCiovCgojaW5jbHVkZSA8Yml0cy9zdGRjKysuaD4KdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCmNsYXNzIFNvbHV0aW9uIHsKcHVibGljOgogICAgdXNpbmcgbGwgPSBsb25nIGxvbmc7CgogICAgY29uc3QgbGwgTkVHID0gLSgxTEwgPDwgNjApOwogICAgY29uc3QgbGwgUE9TID0gICgxTEwgPDwgNjApOwoKICAgIGludCBuOwogICAgdmVjdG9yPHZlY3RvcjxpbnQ+PiBnOwogICAgdmVjdG9yPGxsPiB2YWw7CgogICAgdmVjdG9yPGxsPiBkb3duTWF4LCBkb3duTWluOwogICAgbGwgYW5zd2VyID0gMDsKCiAgICB2b2lkIGRmc0Rvd24oaW50IHUsIGludCBwKSB7CiAgICAgICAgZG93bk1heFt1XSA9IE5FRzsKICAgICAgICBkb3duTWluW3VdID0gUE9TOwoKICAgICAgICBib29sIGhhc0NoaWxkID0gZmFsc2U7CgogICAgICAgIGZvciAoaW50IHYgOiBnW3VdKSB7CiAgICAgICAgICAgIGlmICh2ID09IHApIGNvbnRpbnVlOwoKICAgICAgICAgICAgaGFzQ2hpbGQgPSB0cnVlOwogICAgICAgICAgICBkZnNEb3duKHYsIHUpOwoKICAgICAgICAgICAgZG93bk1heFt1XSA9IG1heChkb3duTWF4W3VdLCB2YWxbdV0gKyBkb3duTWF4W3ZdKTsKICAgICAgICAgICAgZG93bk1pblt1XSA9IG1pbihkb3duTWluW3VdLCB2YWxbdV0gKyBkb3duTWluW3ZdKTsKICAgICAgICB9CgogICAgICAgIGlmICghaGFzQ2hpbGQpIHsKICAgICAgICAgICAgZG93bk1heFt1XSA9IHZhbFt1XTsKICAgICAgICAgICAgZG93bk1pblt1XSA9IHZhbFt1XTsKICAgICAgICB9CiAgICB9CgogICAgdm9pZCBkZnNSZXJvb3QoaW50IHUsIGludCBwLCBsbCBmcm9tUGFyZW50TWF4LCBsbCBmcm9tUGFyZW50TWluKSB7CiAgICAgICAgdmVjdG9yPHBhaXI8bGwsIGludD4+IG1heENhbmQ7CiAgICAgICAgdmVjdG9yPHBhaXI8bGwsIGludD4+IG1pbkNhbmQ7CgogICAgICAgIGlmIChmcm9tUGFyZW50TWF4ICE9IE5FRykgewogICAgICAgICAgICBtYXhDYW5kLnB1c2hfYmFjayh7ZnJvbVBhcmVudE1heCwgcH0pOwogICAgICAgICAgICBtaW5DYW5kLnB1c2hfYmFjayh7ZnJvbVBhcmVudE1pbiwgcH0pOwogICAgICAgIH0KCiAgICAgICAgZm9yIChpbnQgdiA6IGdbdV0pIHsKICAgICAgICAgICAgaWYgKHYgPT0gcCkgY29udGludWU7CgogICAgICAgICAgICBtYXhDYW5kLnB1c2hfYmFjayh7ZG93bk1heFt2XSwgdn0pOwogICAgICAgICAgICBtaW5DYW5kLnB1c2hfYmFjayh7ZG93bk1pblt2XSwgdn0pOwogICAgICAgIH0KCiAgICAgICAgaWYgKCFtYXhDYW5kLmVtcHR5KCkpIHsKICAgICAgICAgICAgbGwgcm9vdE1heCA9IHZhbFt1XSArIG1heF9lbGVtZW50KG1heENhbmQuYmVnaW4oKSwgbWF4Q2FuZC5lbmQoKSktPmZpcnN0OwogICAgICAgICAgICBsbCByb290TWluID0gdmFsW3VdICsgbWluX2VsZW1lbnQobWluQ2FuZC5iZWdpbigpLCBtaW5DYW5kLmVuZCgpKS0+Zmlyc3Q7CgogICAgICAgICAgICBhbnN3ZXIgPSBtYXgoYW5zd2VyLCByb290TWF4IC0gcm9vdE1pbik7CiAgICAgICAgfQoKICAgICAgICBmb3IgKGludCB2IDogZ1t1XSkgewogICAgICAgICAgICBpZiAodiA9PSBwKSBjb250aW51ZTsKCiAgICAgICAgICAgIGxsIGJlc3RNYXggPSBORUc7CiAgICAgICAgICAgIGxsIGJlc3RNaW4gPSBQT1M7CgogICAgICAgICAgICBmb3IgKGF1dG8gW3gsIGlkXSA6IG1heENhbmQpIHsKICAgICAgICAgICAgICAgIGlmIChpZCAhPSB2KSBiZXN0TWF4ID0gbWF4KGJlc3RNYXgsIHgpOwogICAgICAgICAgICB9CgogICAgICAgICAgICBmb3IgKGF1dG8gW3gsIGlkXSA6IG1pbkNhbmQpIHsKICAgICAgICAgICAgICAgIGlmIChpZCAhPSB2KSBiZXN0TWluID0gbWluKGJlc3RNaW4sIHgpOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsbCBwYXNzTWF4ID0gKGJlc3RNYXggPT0gTkVHID8gdmFsW3VdIDogdmFsW3VdICsgYmVzdE1heCk7CiAgICAgICAgICAgIGxsIHBhc3NNaW4gPSAoYmVzdE1pbiA9PSBQT1MgPyB2YWxbdV0gOiB2YWxbdV0gKyBiZXN0TWluKTsKCiAgICAgICAgICAgIGRmc1Jlcm9vdCh2LCB1LCBwYXNzTWF4LCBwYXNzTWluKTsKICAgICAgICB9CiAgICB9CgogICAgbG9uZyBsb25nIGJlc3RSb290VmFsdWUodmVjdG9yPGludD4mIGNhbmRpZXMsIHZlY3Rvcjx2ZWN0b3I8aW50Pj4mIGVkZ2VzKSB7CiAgICAgICAgbiA9IGNhbmRpZXMuc2l6ZSgpOwoKICAgICAgICBpZiAobiA9PSAxKSByZXR1cm4gMDsKCiAgICAgICAgdmFsLmFzc2lnbihuLCAwKTsKCiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBuOyBpKyspIHsKICAgICAgICAgICAgdmFsW2ldID0gY2FuZGllc1tpXTsKICAgICAgICB9CgogICAgICAgIGcuYXNzaWduKG4sIHt9KTsKCiAgICAgICAgZm9yIChhdXRvICZlIDogZWRnZXMpIHsKICAgICAgICAgICAgaW50IHUgPSBlWzBdIC0gMTsKICAgICAgICAgICAgaW50IHYgPSBlWzFdIC0gMTsKCiAgICAgICAgICAgIGdbdV0ucHVzaF9iYWNrKHYpOwogICAgICAgICAgICBnW3ZdLnB1c2hfYmFjayh1KTsKICAgICAgICB9CgogICAgICAgIGRvd25NYXguYXNzaWduKG4sIE5FRyk7CiAgICAgICAgZG93bk1pbi5hc3NpZ24obiwgUE9TKTsKCiAgICAgICAgZGZzRG93bigwLCAtMSk7CiAgICAgICAgZGZzUmVyb290KDAsIC0xLCBORUcsIFBPUyk7CgogICAgICAgIHJldHVybiBhbnN3ZXI7CiAgICB9Cn07CgppbnQgbWFpbigpIHsKICAgIFNvbHV0aW9uIHNvbDsKCiAgICB2ZWN0b3I8aW50PiBjYW5kaWVzID0gezYsIDIsIDksIDF9OwoKICAgIHZlY3Rvcjx2ZWN0b3I8aW50Pj4gZWRnZXMgPSB7CiAgICAgICAgezEsIDJ9LAogICAgICAgIHsyLCAzfSwKICAgICAgICB7MiwgNH0KICAgIH07CgogICAgY291dCA8PCBzb2wuYmVzdFJvb3RWYWx1ZShjYW5kaWVzLCBlZGdlcykgPDwgZW5kbDsKCiAgICByZXR1cm4gMDsKfQ==