Skip to content

Commit 4467c23

Browse files
committed
Sync LeetCode submission Runtime - 227 ms (60.00%), Memory - 60.2 MB (69.15%)
1 parent 613e0ef commit 4467c23

File tree

2 files changed

+139
-0
lines changed

2 files changed

+139
-0
lines changed
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<p>There is an undirected tree with <code>n</code> nodes labeled from <code>0</code> to <code>n - 1</code>, rooted at node <code>0</code>. You are given a 2D integer array <code>edges</code> of length <code>n - 1</code> where <code>edges[i] = [a<sub>i</sub>, b<sub>i</sub>]</code> indicates that there is an edge between nodes <code>a<sub>i</sub></code> and <code>b<sub>i</sub></code> in the tree.</p>
2+
3+
<p>At every node <code>i</code>, there is a gate. You are also given an array of even integers <code>amount</code>, where <code>amount[i]</code> represents:</p>
4+
5+
<ul>
6+
<li>the price needed to open the gate at node <code>i</code>, if <code>amount[i]</code> is negative, or,</li>
7+
<li>the cash reward obtained on opening the gate at node <code>i</code>, otherwise.</li>
8+
</ul>
9+
10+
<p>The game goes on as follows:</p>
11+
12+
<ul>
13+
<li>Initially, Alice is at node <code>0</code> and Bob is at node <code>bob</code>.</li>
14+
<li>At every second, Alice and Bob <b>each</b> move to an adjacent node. Alice moves towards some <strong>leaf node</strong>, while Bob moves towards node <code>0</code>.</li>
15+
<li>For <strong>every</strong> node along their path, Alice and Bob either spend money to open the gate at that node, or accept the reward. Note that:
16+
<ul>
17+
<li>If the gate is <strong>already open</strong>, no price will be required, nor will there be any cash reward.</li>
18+
<li>If Alice and Bob reach the node <strong>simultaneously</strong>, they share the price/reward for opening the gate there. In other words, if the price to open the gate is <code>c</code>, then both Alice and Bob pay&nbsp;<code>c / 2</code> each. Similarly, if the reward at the gate is <code>c</code>, both of them receive <code>c / 2</code> each.</li>
19+
</ul>
20+
</li>
21+
<li>If Alice reaches a leaf node, she stops moving. Similarly, if Bob reaches node <code>0</code>, he stops moving. Note that these events are <strong>independent</strong> of each other.</li>
22+
</ul>
23+
24+
<p>Return<em> the <strong>maximum</strong> net income Alice can have if she travels towards the optimal leaf node.</em></p>
25+
26+
<p>&nbsp;</p>
27+
<p><strong class="example">Example 1:</strong></p>
28+
<img alt="" src="https://assets.leetcode.com/uploads/2022/10/29/eg1.png" style="width: 275px; height: 275px;" />
29+
<pre>
30+
<strong>Input:</strong> edges = [[0,1],[1,2],[1,3],[3,4]], bob = 3, amount = [-2,4,2,-4,6]
31+
<strong>Output:</strong> 6
32+
<strong>Explanation:</strong>
33+
The above diagram represents the given tree. The game goes as follows:
34+
- Alice is initially on node 0, Bob on node 3. They open the gates of their respective nodes.
35+
Alice&#39;s net income is now -2.
36+
- Both Alice and Bob move to node 1.
37+
&nbsp; Since they reach here simultaneously, they open the gate together and share the reward.
38+
&nbsp; Alice&#39;s net income becomes -2 + (4 / 2) = 0.
39+
- Alice moves on to node 3. Since Bob already opened its gate, Alice&#39;s income remains unchanged.
40+
&nbsp; Bob moves on to node 0, and stops moving.
41+
- Alice moves on to node 4 and opens the gate there. Her net income becomes 0 + 6 = 6.
42+
Now, neither Alice nor Bob can make any further moves, and the game ends.
43+
It is not possible for Alice to get a higher net income.
44+
</pre>
45+
46+
<p><strong class="example">Example 2:</strong></p>
47+
<img alt="" src="https://assets.leetcode.com/uploads/2022/10/29/eg2.png" style="width: 250px; height: 78px;" />
48+
<pre>
49+
<strong>Input:</strong> edges = [[0,1]], bob = 1, amount = [-7280,2350]
50+
<strong>Output:</strong> -7280
51+
<strong>Explanation:</strong>
52+
Alice follows the path 0-&gt;1 whereas Bob follows the path 1-&gt;0.
53+
Thus, Alice opens the gate at node 0 only. Hence, her net income is -7280.
54+
</pre>
55+
56+
<p>&nbsp;</p>
57+
<p><strong>Constraints:</strong></p>
58+
59+
<ul>
60+
<li><code>2 &lt;= n &lt;= 10<sup>5</sup></code></li>
61+
<li><code>edges.length == n - 1</code></li>
62+
<li><code>edges[i].length == 2</code></li>
63+
<li><code>0 &lt;= a<sub>i</sub>, b<sub>i</sub> &lt; n</code></li>
64+
<li><code>a<sub>i</sub> != b<sub>i</sub></code></li>
65+
<li><code>edges</code> represents a valid tree.</li>
66+
<li><code>1 &lt;= bob &lt; n</code></li>
67+
<li><code>amount.length == n</code></li>
68+
<li><code>amount[i]</code> is an <strong>even</strong> integer in the range <code>[-10<sup>4</sup>, 10<sup>4</sup>]</code>.</li>
69+
</ul>
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Approach 1: Depth-First Search and Breadth-First Search
2+
3+
# Time: O(n)
4+
# Space: O(n)
5+
6+
from collections import deque
7+
8+
class Solution:
9+
def __init__(self):
10+
self.bob_path = {}
11+
self.visited = []
12+
self.tree = []
13+
14+
15+
def mostProfitablePath(self, edges: List[List[int]], bob: int, amount: List[int]) -> int:
16+
n = len(amount)
17+
max_income = float('-inf')
18+
self.tree = [[] for _ in range(n)]
19+
self.bob_path = {}
20+
self.visited = [False] * n
21+
node_queue = deque([(0, 0, 0)])
22+
23+
for edge in edges:
24+
self.tree[edge[0]].append(edge[1])
25+
self.tree[edge[1]].append(edge[0])
26+
27+
self.find_bob_path(bob, 0)
28+
29+
# BFS
30+
self.visited = [False] * n
31+
while node_queue:
32+
source_node, time, income = node_queue.popleft()
33+
34+
# Alice reaches node first
35+
if source_node not in self.bob_path or time < self.bob_path[source_node]:
36+
income += amount[source_node]
37+
# Reach the node at the same time
38+
elif time == self.bob_path[source_node]:
39+
income += amount[source_node] // 2
40+
41+
# Update max value if current node is a new leaf
42+
if len(self.tree[source_node]) == 1 and source_node != 0:
43+
max_income = max(max_income, income)
44+
45+
# Explore adjacent unvisited vertices
46+
for adj_node in self.tree[source_node]:
47+
if not self.visited[adj_node]:
48+
node_queue.append((adj_node, time + 1, income))
49+
50+
# Mark and remove current node
51+
self.visited[source_node] = True
52+
53+
return max_income
54+
55+
# DFS
56+
def find_bob_path(self, source_node, time):
57+
self.bob_path[source_node] = time
58+
self.visited[source_node] = True
59+
60+
if source_node == 0:
61+
return True
62+
63+
for adj_node in self.tree[source_node]:
64+
if not self.visited[adj_node]:
65+
if self.find_bob_path(adj_node, time + 1):
66+
return True
67+
68+
# If node 0 isn't reached, remove current node from path
69+
self.bob_path.pop(source_node, None)
70+
return False

0 commit comments

Comments
 (0)