01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package algs42;
import stdlib.*;
import algs13.Bag;
/* ***********************************************************************
 *  Compilation:  javac DirectedDFS.java
 *  Execution:    java DirectedDFS V E
 *  Dependencies: Digraph.java Bag.java In.java StdOut.java
 *  Data files:   http://www.cs.princeton.edu/algs4/42directed/tinyDG.txt
 *
 *  Determine single-source or multiple-source reachability in a digraph
 *  using depth first search.
 *  Runs in O(E + V) time.
 *
 *  % java DirectedDFS tinyDG.txt 1
 *  1
 *
 *  % java DirectedDFS tinyDG.txt 2
 *  0 1 2 3 4 5
 *
 *  % java DirectedDFS tinyDG.txt 1 2 6
 *  0 1 2 3 4 5 6 9 10 11 12
 *
 *************************************************************************/

public class DirectedDFS {
  private final boolean[] marked;  // marked[v] = true if v is reachable
  // from source (or sources)

  // single-source reachability
  public DirectedDFS(Digraph G, int s) {
    marked = new boolean[G.V()];
    dfs(G, s);
  }

  // multiple-source reachability
  public DirectedDFS(Digraph G, Iterable<Integer> sources) {
    marked = new boolean[G.V()];
    for (int v : sources)
      dfs(G, v);
  }

  private void dfs(Digraph G, int v) {
    marked[v] = true;
    for (int w : G.adj(v)) {
      if (!marked[w]) dfs(G, w);
    }
  }

  // is there a directed path from the source (or sources) to v?
  public boolean marked(int v) {
    return marked[v];
  }

  // test client
  public static void main(String[] args) {
    //args = new String[] { "data/tinyDG.txt", "1" };
    args = new String[] { "data/tinyDG.txt", "2" };
    //args = new String[] { "data/tinyDG.txt", "1", "2", "6" };

    // read in digraph from command-line argument
    In in = new In(args[0]);
    Digraph G = DigraphGenerator.fromIn(in);

    // read in sources from command-line arguments
    Bag<Integer> sources = new Bag<>();
    for (int i = 1; i < args.length; i++) {
      int s = Integer.parseInt(args[i]);
      sources.add(s);
    }

    // multiple-source reachability
    DirectedDFS dfs = new DirectedDFS(G, sources);

    // print out vertices reachable from sources
    for (int v = 0; v < G.V(); v++) {
      if (dfs.marked(v)) StdOut.print(v + " ");
    }
    StdOut.println();
  }

}