Approach
Depth-first search
For Find the Last Marked Nodes in Tree, the implementation follows one branch at a time, making it suitable for components, trees, backtracking, or dependency exploration.
- Define the state carried into one recursive or stack frame.
- Mark or choose the current state before exploring children.
- Combine child results or undo the choice when the branch finishes.
Code notes
- 90 lines of Python from the credited upstream file 3313.py.
- The implementation visibly relies on sequence storage, cached states.
- No explicit loop blocks detected, together with recursive traversal.
Complexity
Count unique states for graph traversal; for backtracking, count the branching factor and maximum depth.
Check the problem constraints before deciding whether this complexity will pass.
Use this to learn the idea, then write your own version.
1from dataclasses import dataclass2 3 4@dataclass5class Node:6 node: int = 0 7 time: int = 0 8 9 10class Last2:11 def __init__(self, last1: Node = Node(), last2: Node = Node()):12 self.last1 = last1 13 self.last2 = last2 14 15 16class Solution:17 18 def lastMarkedNodes(self, edges: list[list[int]]) -> list[int]:19 n = len(edges) + 120 ans = [0] * n21 tree = [[] for _ in range(n)]22 23 24 dp = [Last2()] * n25 26 for u, v in edges:27 tree[u].append(v)28 tree[v].append(u)29 30 self._dfs(tree, 0, -1, dp)31 self._reroot(tree, 0, -1, Node(), dp, ans)32 return ans33 34 def _dfs(35 self,36 tree: list[list[int]],37 u: int,38 prev: int,39 dp: list[Last2]40 ) -> Node:41 """42 Performs a DFS traversal of the subtree rooted at node `u`, computes the43 time taken to mark all nodes in the subtree, records the last two marked44 nodes, and returns the last marked node.45 46 These values are used later in the rerooting process.47 """48 last1 = Node(u, 0)49 last2 = Node()50 for v in tree[u]:51 if v == prev:52 continue53 child = self._dfs(tree, v, u, dp)54 time = child.time + 155 if time > last1.time:56 last2 = last157 last1 = Node(child.node, time)58 elif time > last2.time:59 last2 = Node(child.node, time)60 dp[u] = Last2(last1, last2)61 return last162 63 def _reroot(64 self,65 tree: list[list[int]],66 u: int,67 prev: int,68 last: Node,69 dp: list[list[int]],70 ans: list[int]71 ) -> None:72 """73 Reroots the tree at node `u` and updates the answer array, where `last`74 is the last marked node that doesn't go through `u`'s subtree.75 """76 ans[u] = last.node if last.time > dp[u].last1.time else dp[u].last1.node77 for v in tree[u]:78 if v == prev:79 continue80 newLast = Node(last.node, last.time + 1)81 if dp[u].last1.node == dp[v].last1.node:82 alternativeTime = 1 + dp[u].last2.time83 if alternativeTime > newLast.time:84 newLast = Node(dp[u].last2.node, alternativeTime)85 else:86 alternativeTime = 1 + dp[u].last1.time87 if alternativeTime > newLast.time:88 newLast = Node(dp[u].last1.node, alternativeTime)89 self._reroot(tree, v, u, newLast, dp, ans)90