/****************************************************************************** * Compilation: javac DepthFirstDirectedPaths.java * Execution: java DepthFirstDirectedPaths digraph.txt s * Dependencies: Digraph.java Stack.java * Data files: https://algs4.cs.princeton.edu/42digraph/tinyDG.txt * https://algs4.cs.princeton.edu/42digraph/mediumDG.txt * https://algs4.cs.princeton.edu/42digraph/largeDG.txt * * Determine reachability in a digraph from a given vertex using * depth-first search. * Runs in O(E + V) time. * * % java DepthFirstDirectedPaths tinyDG.txt 3 * 3 to 0: 3-5-4-2-0 * 3 to 1: 3-5-4-2-0-1 * 3 to 2: 3-5-4-2 * 3 to 3: 3 * 3 to 4: 3-5-4 * 3 to 5: 3-5 * 3 to 6: not connected * 3 to 7: not connected * 3 to 8: not connected * 3 to 9: not connected * 3 to 10: not connected * 3 to 11: not connected * 3 to 12: not connected * ******************************************************************************/ /** * The {@code DepthFirstDirectedPaths} class represents a data type for * finding directed paths from a source vertex s to every * other vertex in the digraph. *
* This implementation uses depth-first search. * The constructor takes Θ(V + E) time in the * worst case, where V is the number of vertices and E * is the number of edges. * Each instance method takes Θ(1) time. * It uses Θ(V) extra space (not including the digraph). *
* See {@link DepthFirstDirectedPaths} for a nonrecursive implementation.
* For additional documentation,
* see Section 4.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class DepthFirstDirectedPaths {
private boolean[] marked; // marked[v] = true iff v is reachable from s
private int[] edgeTo; // edgeTo[v] = last edge on path from s to v
private final int s; // source vertex
/**
* Computes a directed path from {@code s} to every other vertex in digraph {@code G}.
* @param G the digraph
* @param s the source vertex
* @throws IllegalArgumentException unless {@code 0 <= s < V}
*/
public DepthFirstDirectedPaths(Digraph G, int s) {
marked = new boolean[G.V()];
edgeTo = new int[G.V()];
this.s = s;
validateVertex(s);
dfs(G, s);
}
private void dfs(Digraph G, int v) {
marked[v] = true;
for (int w : G.adj(v)) {
if (!marked[w]) {
edgeTo[w] = v;
dfs(G, w);
}
}
}
/**
* Is there a directed path from the source vertex {@code s} to vertex {@code v}?
* @param v the vertex
* @return {@code true} if there is a directed path from the source
* vertex {@code s} to vertex {@code v}, {@code false} otherwise
* @throws IllegalArgumentException unless {@code 0 <= v < V}
*/
public boolean hasPathTo(int v) {
validateVertex(v);
return marked[v];
}
/**
* Returns a directed path from the source vertex {@code s} to vertex {@code v}, or
* {@code null} if no such path.
* @param v the vertex
* @return the sequence of vertices on a directed path from the source vertex
* {@code s} to vertex {@code v}, as an Iterable
* @throws IllegalArgumentException unless {@code 0 <= v < V}
*/
public Iterable