All Ancestors of a Node in a Directed Acyclic Graph

medium topological sort dag

Problem

You are given a directed acyclic graph with n nodes labeled 0 to n − 1 (1 ≤ n ≤ 1000) and a list of edges where [u, v] denotes a directed edge from u to v. A node u is an ancestor of v if u can reach v by following one or more directed edges.

Return a list answer where answer[i] holds all distinct ancestors of node i sorted in ascending order. The graph has no cycles and no duplicate edges.

Inputn = 8, edges = [[0,3],[0,4],[1,3],[2,4],[2,7],[3,5],[3,6],[3,7],[4,6]]
Output[[],[],[],[0,1],[0,2],[0,1,3],[0,1,2,3,4],[0,1,2,3]]
Nodes 0, 1 and 2 have no incoming edges, so no ancestors; node 6 can be reached from 0, 1, 2, 3 and 4.

from collections import deque

def get_ancestors(n, edges):
    adj = [[] for _ in range(n)]
    indeg = [0] * n
    for u, v in edges:
        adj[u].append(v)
        indeg[v] += 1
    anc = [set() for _ in range(n)]
    q = deque(i for i in range(n) if indeg[i] == 0)
    while q:
        u = q.popleft()
        for v in adj[u]:
            anc[v].add(u)
            anc[v] |= anc[u]
            indeg[v] -= 1
            if indeg[v] == 0:
                q.append(v)
    return [sorted(a) for a in anc]
function getAncestors(n, edges) {
  const adj = Array.from({ length: n }, () => []);
  const indeg = new Array(n).fill(0);
  for (const [u, v] of edges) {
    adj[u].push(v);
    indeg[v]++;
  }
  const anc = Array.from({ length: n }, () => new Set());
  const q = [];
  for (let i = 0; i < n; i++) if (indeg[i] === 0) q.push(i);
  for (let head = 0; head < q.length; head++) {
    const u = q[head];
    for (const v of adj[u]) {
      anc[v].add(u);
      for (const a of anc[u]) anc[v].add(a);
      if (--indeg[v] === 0) q.push(v);
    }
  }
  return anc.map(s => [...s].sort((a, b) => a - b));
}
List<List<Integer>> getAncestors(int n, int[][] edges) {
    List<List<Integer>> adj = new ArrayList<>();
    List<TreeSet<Integer>> anc = new ArrayList<>();
    int[] indeg = new int[n];
    for (int i = 0; i < n; i++) {
        adj.add(new ArrayList<>());
        anc.add(new TreeSet<>());
    }
    for (int[] e : edges) {
        adj.get(e[0]).add(e[1]);
        indeg[e[1]]++;
    }
    Deque<Integer> q = new ArrayDeque<>();
    for (int i = 0; i < n; i++) if (indeg[i] == 0) q.add(i);
    while (!q.isEmpty()) {
        int u = q.poll();
        for (int v : adj.get(u)) {
            anc.get(v).add(u);
            anc.get(v).addAll(anc.get(u));
            if (--indeg[v] == 0) q.add(v);
        }
    }
    List<List<Integer>> res = new ArrayList<>();
    for (TreeSet<Integer> s : anc) res.add(new ArrayList<>(s));
    return res;
}
vector<vector<int>> getAncestors(int n, vector<vector<int>>& edges) {
    vector<vector<int>> adj(n);
    vector<set<int>> anc(n);
    vector<int> indeg(n, 0);
    for (auto& e : edges) {
        adj[e[0]].push_back(e[1]);
        indeg[e[1]]++;
    }
    queue<int> q;
    for (int i = 0; i < n; i++) if (indeg[i] == 0) q.push(i);
    while (!q.empty()) {
        int u = q.front(); q.pop();
        for (int v : adj[u]) {
            anc[v].insert(u);
            anc[v].insert(anc[u].begin(), anc[u].end());
            if (--indeg[v] == 0) q.push(v);
        }
    }
    vector<vector<int>> res(n);
    for (int i = 0; i < n; i++) res[i] = vector<int>(anc[i].begin(), anc[i].end());
    return res;
}
Time: O(n·(n + m)) Space: O(n²)