/**
   * Returns a random rooted-out DAG on <tt>V</tt> vertices and <tt>E</tt> edges. The DAG returned
   * is not chosen uniformly at random among all such DAGs.
   *
   * @param V the number of vertices
   * @param E the number of edges
   * @return a random rooted-out DAG on <tt>V</tt> vertices and <tt>E</tt> edges
   */
  public static Digraph rootedOutDAG(int V, int E) {
    if (E > (long) V * (V - 1) / 2) throw new IllegalArgumentException("Too many edges");
    if (E < V - 1) throw new IllegalArgumentException("Too few edges");
    Digraph G = new Digraph(V);
    SET<Edge> set = new SET<Edge>();

    // fix a topological order
    int[] vertices = new int[V];
    for (int i = 0; i < V; i++) vertices[i] = i;
    StdRandom.shuffle(vertices);

    // one edge pointing from each vertex, other than the root = vertices[V-1]
    for (int v = 0; v < V - 1; v++) {
      int w = StdRandom.uniform(v + 1, V);
      Edge e = new Edge(v, w);
      set.add(e);
      G.addEdge(vertices[w], vertices[v]);
    }

    while (G.E() < E) {
      int v = StdRandom.uniform(V);
      int w = StdRandom.uniform(V);
      Edge e = new Edge(v, w);
      if ((v < w) && !set.contains(e)) {
        set.add(e);
        G.addEdge(vertices[w], vertices[v]);
      }
    }
    return G;
  }
Beispiel #2
0
  public static void main(String[] args) {

    In in1 = new In(Inputs.DIGRAPH_SMALL);
    In in2 = new In(Inputs.DIGRAPH_SMALL);
    edu.princeton.cs.algs4.Digraph sedgewicks = new edu.princeton.cs.algs4.Digraph(in1);
    Digraph digraph = new Digraph(in2);
    in1.close();
    in2.close();

    StdOut.printf("Sedgewicks - v: %d, e: %d\n", sedgewicks.V(), sedgewicks.E());
    for (int i = 0; i < sedgewicks.V(); i++) {
      for (int w : sedgewicks.adj(i)) {
        StdOut.printf("%d -> %d\n", i, w);
      }
    }
    StdOut.println();

    StdOut.printf("My - v: %d, e: %d\n", digraph.V(), digraph.E());
    for (int i = 0; i < digraph.V(); i++) {
      for (int w : digraph.adj(i)) {
        StdOut.printf("%d -> %d\n", i, w);
      }
    }
    StdOut.println();

    edu.princeton.cs.algs4.Digraph sedwickDi = sedgewicks.reverse();
    StdOut.printf("Sedgewicks reverse - v: %d, e: %d\n", sedwickDi.V(), sedwickDi.E());
    for (int i = 0; i < sedwickDi.V(); i++) {
      for (int w : sedwickDi.adj(i)) {
        StdOut.printf("%d -> %d\n", i, w);
      }
    }
    StdOut.println();

    Digraph myReverse = digraph.reverse();
    StdOut.printf("My reverse - v: %d, e: %d\n", myReverse.V(), myReverse.E());
    for (int i = 0; i < myReverse.V(); i++) {
      for (int w : myReverse.adj(i)) {
        StdOut.printf("%d -> %d\n", i, w);
      }
    }
  }
Beispiel #3
0
 /** Copy constructor. */
 public Digraph(Digraph G) {
   this(G.V());
   this.E = G.E();
   for (int v = 0; v < G.V(); v++) {
     // reverse so that adjacency list is in same order as original
     Stack<Integer> reverse = new Stack<Integer>();
     for (int w : G.adj[v]) {
       reverse.push(w);
     }
     for (int w : reverse) {
       adj[v].add(w);
     }
   }
 }
  /**
   * Computes an Eulerian cycle in the specified digraph, if one exists.
   *
   * @param G the digraph
   */
  public DirectedEulerianCycle(Digraph G) {

    // must have at least one edge
    if (G.E() == 0) return;

    // necessary condition: indegree(v) = outdegree(v) for each vertex v
    // (without this check, DFS might return a path instead of a cycle)
    for (int v = 0; v < G.V(); v++) if (G.outdegree(v) != G.indegree(v)) return;

    // create local view of adjacency lists, to iterate one vertex at a time
    Iterator<Integer>[] adj = (Iterator<Integer>[]) new Iterator[G.V()];
    for (int v = 0; v < G.V(); v++) adj[v] = G.adj(v).iterator();

    // initialize stack with any non-isolated vertex
    int s = nonIsolatedVertex(G);
    Stack<Integer> stack = new Stack<Integer>();
    stack.push(s);

    // greedily add to putative cycle, depth-first search style
    cycle = new Stack<Integer>();
    while (!stack.isEmpty()) {
      int v = stack.pop();
      while (adj[v].hasNext()) {
        stack.push(v);
        v = adj[v].next();
      }
      // add vertex with no more leaving edges to cycle
      cycle.push(v);
    }

    // check if all edges have been used
    // (in case there are two or more vertex-disjoint Eulerian cycles)
    if (cycle.size() != G.E() + 1) cycle = null;

    assert certifySolution(G);
  }
 /**
  * Returns a random simple digraph containing <tt>V</tt> vertices and <tt>E</tt> edges.
  *
  * @param V the number of vertices
  * @param E the number of vertices
  * @return a random simple digraph on <tt>V</tt> vertices, containing a total of <tt>E</tt> edges
  * @throws IllegalArgumentException if no such simple digraph exists
  */
 public static Digraph simple(int V, int E) {
   if (E > (long) V * (V - 1)) throw new IllegalArgumentException("Too many edges");
   if (E < 0) throw new IllegalArgumentException("Too few edges");
   Digraph G = new Digraph(V);
   SET<Edge> set = new SET<Edge>();
   while (G.E() < E) {
     int v = StdRandom.uniform(V);
     int w = StdRandom.uniform(V);
     Edge e = new Edge(v, w);
     if ((v != w) && !set.contains(e)) {
       set.add(e);
       G.addEdge(v, w);
     }
   }
   return G;
 }
 /**
  * Returns a random simple DAG containing <tt>V</tt> vertices and <tt>E</tt> edges. Note: it is
  * not uniformly selected at random among all such DAGs.
  *
  * @param V the number of vertices
  * @param E the number of vertices
  * @return a random simple DAG on <tt>V</tt> vertices, containing a total of <tt>E</tt> edges
  * @throws IllegalArgumentException if no such simple DAG exists
  */
 public static Digraph dag(int V, int E) {
   if (E > (long) V * (V - 1) / 2) throw new IllegalArgumentException("Too many edges");
   if (E < 0) throw new IllegalArgumentException("Too few edges");
   Digraph G = new Digraph(V);
   SET<Edge> set = new SET<Edge>();
   int[] vertices = new int[V];
   for (int i = 0; i < V; i++) vertices[i] = i;
   StdRandom.shuffle(vertices);
   while (G.E() < E) {
     int v = StdRandom.uniform(V);
     int w = StdRandom.uniform(V);
     Edge e = new Edge(v, w);
     if ((v < w) && !set.contains(e)) {
       set.add(e);
       G.addEdge(vertices[v], vertices[w]);
     }
   }
   return G;
 }
  // check that solution is correct
  private boolean certifySolution(Digraph G) {

    // internal consistency check
    if (hasEulerianCycle() == (cycle() == null)) return false;

    // hashEulerianCycle() returns correct value
    if (hasEulerianCycle() != hasEulerianCycle(G)) return false;

    // nothing else to check if no Eulerian cycle
    if (cycle == null) return true;

    // check that cycle() uses correct number of edges
    if (cycle.size() != G.E() + 1) return false;

    // check that cycle() is a directed cycle of G
    // TODO

    return true;
  }
  // Determines whether a digraph has an Eulerian cycle using necessary
  // and sufficient conditions (without computing the cycle itself):
  //    - at least one edge
  //    - indegree(v) = outdegree(v) for every vertex
  //    - the graph is connected, when viewed as an undirected graph
  //      (ignoring isolated vertices)
  private static boolean hasEulerianCycle(Digraph G) {

    // Condition 0: at least 1 edge
    if (G.E() == 0) return false;

    // Condition 1: indegree(v) == outdegree(v) for every vertex
    for (int v = 0; v < G.V(); v++) if (G.outdegree(v) != G.indegree(v)) return false;

    // Condition 2: graph is connected, ignoring isolated vertices
    Graph H = new Graph(G.V());
    for (int v = 0; v < G.V(); v++) for (int w : G.adj(v)) H.addEdge(v, w);

    // check that all non-isolated vertices are conneted
    int s = nonIsolatedVertex(G);
    BreadthFirstPaths bfs = new BreadthFirstPaths(H, s);
    for (int v = 0; v < G.V(); v++) if (H.degree(v) > 0 && !bfs.hasPathTo(v)) return false;

    return true;
  }