Solution
Time Complexity: O(n) Space: O(N)
-
Build the Tree: Use an graph to represent the undirected tree.
-
DFS: Bob going up, Alice going down
-
Find Bob’s Arrival Times
-
DFS from Bob’s starting node toward node 0.
-
Record, in bobPath[node], the time Bob arrives.
-
Only keep nodes in bobPath that actually lie on Bob’s route to 0.
-
-
Explore Alice’s Routes
- DFS from node 0 to every leaf.
-
Compare Alice’s arrival time with Bob’s stored time:
-
Alice arrives earlier → collects full amount.
-
Arrive simultaneously → collects half the amount.
-
Bob arrives earlier → collects nothing.
-
-
Track the maximum profit at any leaf.
// Result: Return that maximum profit.
class Solution {
private Map<Integer, List<Integer>> tree;
private Map<Integer, Integer> bobPath; // <node, time of arrival>
private boolean[] visited;
private int maxProfit = Integer.MIN_VALUE;
public int mostProfitablePath(int[][] edges, int bob, int[] amount) {
int n = amount.length;
// build tree
tree = new HashMap<>();
for (int i = 0; i < n; i++) {
tree.put(i, new ArrayList<>());
}
for (int[] edge : edges) {
tree.get(edge[0]).add(edge[1]);
tree.get(edge[1]).add(edge[0]);
}
visited = new boolean[n];
bobPath = new HashMap<>();
dfsBob(bob, 0);
// reset
Arrays.fill(visited, false);
dfsAlice(0, 0, 0, amount);
return maxProfit;
}
// Why a boolean return value helps
// signal back up the call stack whether or not the path found node 0.
// false: It means “We did not reach node 0 from here
public boolean dfsBob(int node, int step) {
bobPath.put(node, step);
// to make sure Bob goes only up towards root
visited[node] = true;
// signals Bob found the final path to root
if (node == 0) {
return true;
}
for (int adj : tree.get(node)) {
// shouldn't return dfsBob, we want to explore all adj
if (!visited[adj] && dfsBob(adj, step + 1)) {
return true;
}
}
// current path didn't work after explore all adjs
bobPath.remove(node);
return false;
}
public void dfsAlice(int node, int step, int profit, int[] amount) {
// to make sure alice goes only down to the leaf
visited[node] = true;
// CASE 1: bob didn't visited this node OR bob comes later than alice
if (!bobPath.containsKey(node) || step < bobPath.get(node)) {
profit += amount[node]; // get full credit
}
// CASE 2:arrive same time
else if (step == bobPath.get(node)) {
profit += amount[node] / 2;
}
// CASE 3: bob visited early than alice: alice profit remain same
// Alice reached leaf node
if (tree.get(node).size() == 1 && node != 0) {
maxProfit = Math.max(profit, maxProfit);
}
// explore adjacent nodes
for (int adj : tree.get(node)) {
if (!visited[adj]) {
dfsAlice(adj, step + 1, profit, amount);
}
}
}
}