from collections import defaultdict
class Solution:
def mostProfitablePath(self, edges: List[List[int]], bob: int, amount: List[int]) -> int:
INF = float('inf')
# this stuct maintains the distance from B to A's staring node.
# if a node is not in the path, the distance will the INF.
# Example: [inf, inf, inf, inf, inf] --> [2, 1, inf, 0, inf]
# where nodes 0, 1, and 3 in the path
path_len_from_b_to_a = [INF]*len(amount)
graph = defaultdict(list)
for i, j in edges:
graph[i].append(j)
graph[j].append(i)
def calculate_path(prev_node, node, distance):
if node == 0:
path_len_from_b_to_a[node] = distance
return True
for neighbor in graph[node]:
if neighbor != prev_node:
if calculate_path(node, neighbor, distance+1):
path_len_from_b_to_a[node] = distance
return True
return False
# print(path_len_from_b_to_a)
calculate_path(-1, bob, 0)
# print(path_len_from_b_to_a)
self.max_profit = -float('inf')
# One of the path in traversing all neighbours is same path
# through which A arrived at the current node. This path should not be visited again
# Since this path is already evaluated.
# prev node is passed here to prevent this revisiting.
def find_alice_max(curr, prev, distance, current_income):
# Calculate Alice's share at this node
if distance < path_len_from_b_to_a[curr]:
# this node lies either less than half distance of path_len_from_b_to_a in path from A to B
# OR
# this node is not in path from A to B (INF)
current_income += amount[curr]
elif distance == path_len_from_b_to_a[curr]:
current_income += amount[curr] // 2
# Check if it's a leaf node (not root)
# this a edge case if the root node is a leaf, we should still perform recursion.
if len(graph[curr]) == 1 and curr != 0:
self.max_profit = max(self.max_profit, current_income)
return
for neighbor in graph[curr]:
if neighbor != prev:
find_alice_max(neighbor, curr, distance + 1, current_income)
find_alice_max(0, -1, 0, 0)
return self.max_profit