We want to find the smallest set of vertices from which all other vertices are reachable. A vertex must be in this set if no other vertex can reach it, meaning it has no incoming edges.
Using dfs, we traverse from each unvisited node and mark all reachable nodes. Any node that gets reached from another node can be removed from our candidate set. The nodes that remain are those with no incoming edges.
dfs:res set.class Solution:
def findSmallestSetOfVertices(self, n: int, edges: List[List[int]]) -> List[int]:
adj = [[] for _ in range(n)]
for u, v in edges:
adj[u].append(v)
res = set(range(n))
visited = [False] * n
def dfs(node):
visited[node] = True
for nei in adj[node]:
if not visited[nei]:
dfs(nei)
res.discard(nei)
for i in range(n):
if not visited[i]:
dfs(i)
return list(res)Where is the number of vertices and is the number of edges.
This is the same approach as recursive dfs but uses an explicit stack to avoid recursion. We process nodes iteratively, marking each visited node and removing any node that has an incoming edge from our candidate set.
res.stack for iterative dfs:node from the stack.stack if unvisited and mark as not a res.res.class Solution:
def findSmallestSetOfVertices(self, n: int, edges: List[List[int]]) -> List[int]:
adj = [[] for _ in range(n)]
for u, v in edges:
adj[u].append(v)
res = [True] * n
visited = [False] * n
stack = []
for i in range(n):
if not visited[i]:
stack.append(i)
while stack:
node = stack.pop()
if visited[node]:
continue
visited[node] = True
for nei in adj[node]:
if not visited[nei]:
stack.append(nei)
res[nei] = False
return [i for i in range(n) if res[i]]Where is the number of vertices and is the number of edges.
A vertex needs to be in our starting set only if it cannot be reached from any other vertex. This happens exactly when the vertex has no incoming edges. We can track which vertices have incoming edges by building a list of sources for each destination.
incoming[v] stores all vertices with edges pointing to v.incoming lists.incoming[v] is empty.res.Where is the number of vertices and is the number of edges.
We do not need to store the actual source vertices for each destination. We only care whether a vertex has at least one incoming edge. A simple boolean array is sufficient: mark each destination as having an incoming edge, then return all vertices that were never marked.
indegree of size n, initialized to false.(src, dst), set indegree[dst] = true.i where indegree[i] is false.res.Where is the number of vertices and is the number of edges.
The problem asks for nodes that cannot be reached from other nodes, which means nodes with zero incoming edges. Tracking outgoing edges instead will identify nodes that cannot reach others, which is the opposite of what is needed.
Since the graph is acyclic and we only need nodes with no incoming edges, a simple pass through the edges is sufficient. Implementing full DFS or BFS adds unnecessary complexity and potential for bugs when a simple indegree check solves the problem optimally.