// https://leetcode.com/problems/all-paths-from-source-lead-to-destination // T: O(V + E) // S: O(V) import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; public class AllPathsFromSourceLeadToDestination { // We don't use the state WHITE as such anywhere. Instead, the "null" value in the states array below is a substitute for WHITE. enum Color { GRAY, BLACK }; public boolean leadsToDestination(int n, int[][] edges, int source, int destination) { Map<Integer, Set<Integer>> graph = buildGraph(edges); return leadsToDestination(graph, source, destination, new Color[n]); } private boolean leadsToDestination(Map<Integer, Set<Integer>> graph, int node, int target, Color[] states) { // If the state is GRAY, this is a backward edge and hence, it creates a loop. if (states[node] != null) { return states[node] == Color.BLACK; } // If this is a leaf node, it should be equal to the destination. if (!graph.containsKey(node)) { return node == target; } // Now, we are processing this node. So we mark it as GRAY states[node] = Color.GRAY; for (int next : graph.get(node)) { if (!leadsToDestination(graph, next, target, states)) { return false; } } states[node] = Color.BLACK; return true; } private Map<Integer, Set<Integer>> buildGraph(int[][] edges) { final Map<Integer, Set<Integer>> graph = new HashMap<>(); for (int[] edge : edges) { final int from = edge[0], to = edge[1]; final Set<Integer> neighbours = graph.getOrDefault(from, new HashSet<>()); neighbours.add(to); graph.putIfAbsent(from, neighbours); } return graph; } }