Given a directed acyclic graph, with n
vertices numbered from 0
to n-1
, and an array edges
where edges[i] = [fromi, toi]
represents a directed edge from node fromi
to node toi
.
Find the smallest set of vertices from which all nodes in the graph are reachable. It's guaranteed that a unique solution exists.
Notice that you can return the vertices in any order.
Example 1:
Input: n = 6, edges = [[0,1],[0,2],[2,5],[3,4],[4,2]] Output: [0,3] Explanation: It's not possible to reach all the nodes from a single vertex. From 0 we can reach [0,1,2,5]. From 3 we can reach [3,4,2,5]. So we output [0,3].
Example 2:
Input: n = 5, edges = [[0,1],[2,1],[3,1],[1,4],[2,4]] Output: [0,2,3] Explanation: Notice that vertices 0, 3 and 2 are not reachable from any other node, so we must include them. Also any of these vertices can reach nodes 1 and 4.
Constraints:
2 <= n <= 10^5
1 <= edges.length <= min(10^5, n * (n - 1) / 2)
edges[i].length == 2
0 <= fromi, toi < n
(fromi, toi)
are distinct.This problem asks to find the minimum set of vertices in a directed acyclic graph (DAG) such that all nodes in the graph are reachable from these vertices. The solution leverages the fact that a vertex that is a destination of an edge (incoming edge) does not need to be in the minimum set because it's reachable from its predecessors. Therefore, only vertices with no incoming edges are considered.
The core idea is to count the number of incoming edges for each vertex. If a vertex has zero incoming edges, it must be included in the minimum set because it cannot be reached from any other vertex. Vertices with incoming edges can be reached from other vertices, so they don't need to be explicitly included in the result.
Initialization: Create an array cnt
of size n
(number of vertices) initialized to 0. This array will store the count of incoming edges for each vertex.
Count Incoming Edges: Iterate through the edges
list. For each edge [from, to]
, increment the count of incoming edges for vertex to
( cnt[to]++
).
Identify Source Vertices: Iterate through the cnt
array. If cnt[i]
is 0, it means vertex i
has no incoming edges, so add it to the result list ans
.
Return Result: Return the ans
list containing the vertices with no incoming edges.
Time Complexity: O(N + E), where N is the number of vertices and E is the number of edges. The algorithm iterates through the edges once (O(E)) and then iterates through the vertices once (O(N)).
Space Complexity: O(N). The cnt
array requires O(N) space to store the incoming edge counts for each vertex. The ans
list also requires at most O(N) space in the worst case.
from collections import Counter
class Solution:
def findSmallestSetOfVertices(self, n: int, edges: List[List[int]]) -> List[int]:
cnt = Counter(t for _, t in edges) #Efficient way to count incoming edges using Counter
return [i for i in range(n) if cnt[i] == 0] #List comprehension for concise code
The Python solution utilizes the Counter
object from the collections
module for efficient counting of incoming edges. This eliminates the need for manual iteration and makes the code more readable and potentially faster. The list comprehension elegantly filters and creates the result list.
Other languages follow a similar logic, but the specific syntax and data structures might vary slightly. The core algorithm remains consistent across all languages.