コード例 #1
0
  // 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;
  }
コード例 #2
0
  /**
   * 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);
  }