Find Eventual Safe States

medium graph dfs topological sort

Problem

A directed graph is given as adjacency lists. A node is safe if every path starting from it leads to a terminal node (one with no outgoing edges). Return the sorted list of safe nodes.

Inputgraph = [[1,2],[2,3],[5],[0],[5],[],[]]
Output[2, 4, 5, 6]
5 and 6 are terminals; 2 → 5 and 4 → 5 are safe; 0, 1, 3 sit on a 0→1→3→0 cycle.

def eventual_safe_nodes(graph):
    WHITE, GRAY, BLACK = 0, 1, 2
    color = [WHITE] * len(graph)
    def dfs(u):
        if color[u] != WHITE:
            return color[u] == BLACK
        color[u] = GRAY
        for v in graph[u]:
            if color[v] == BLACK:
                continue
            if color[v] == GRAY or not dfs(v):
                return False
        color[u] = BLACK
        return True
    return [i for i in range(len(graph)) if dfs(i)]
function eventualSafeNodes(graph) {
  const n = graph.length;
  const color = new Array(n).fill(0);
  const dfs = (u) => {
    if (color[u] !== 0) return color[u] === 2;
    color[u] = 1;
    for (const v of graph[u]) {
      if (color[v] === 2) continue;
      if (color[v] === 1 || !dfs(v)) return false;
    }
    color[u] = 2;
    return true;
  };
  const out = [];
  for (let i = 0; i < n; i++) if (dfs(i)) out.push(i);
  return out;
}
class Solution {
    int[] color;
    public List<Integer> eventualSafeNodes(int[][] graph) {
        int n = graph.length;
        color = new int[n];
        List<Integer> out = new ArrayList<>();
        for (int i = 0; i < n; i++) if (dfs(graph, i)) out.add(i);
        return out;
    }
    private boolean dfs(int[][] g, int u) {
        if (color[u] != 0) return color[u] == 2;
        color[u] = 1;
        for (int v : g[u]) {
            if (color[v] == 2) continue;
            if (color[v] == 1 || !dfs(g, v)) return false;
        }
        color[u] = 2;
        return true;
    }
}
class Solution {
public:
    vector<int> color;
    vector<int> eventualSafeNodes(vector<vector<int>>& graph) {
        int n = graph.size();
        color.assign(n, 0);
        vector<int> out;
        for (int i = 0; i < n; i++) if (dfs(graph, i)) out.push_back(i);
        return out;
    }
    bool dfs(vector<vector<int>>& g, int u) {
        if (color[u] != 0) return color[u] == 2;
        color[u] = 1;
        for (int v : g[u]) {
            if (color[v] == 2) continue;
            if (color[v] == 1 || !dfs(g, v)) return false;
        }
        color[u] = 2;
        return true;
    }
};
Time: O(V + E) Space: O(V)