/** * Ejecuta una caminata aleatoria sobre un grafo dirigido. Imprime por pantalla la cantidad de * pasos que dio antes de visitar todos los nodos del grafo. * * @param G Grafo dirigido sobre el cual se desea realizar la caminata aleatoria. */ public void randomWalk(Digraph G) { int cont = 0; if (G.V() == 0) return; boolean[] viewed = new boolean[G.V()]; int node = 0; viewed[node] = true; while (!this.allTrue(viewed)) { if (G.outdegree(node) == 0) { System.out.println("Encontrado un nodo sin salida"); System.out.println("Cantidad de pasos dados en el Random Walk : " + cont); return; } int visited = this.getRandomNode(G.adj(node), G.outdegree(node)); System.out.println(node + " -> " + visited); viewed[visited] = true; cont++; node = visited; } System.out.println("Cantidad de pasos dados en el Random Walk : " + cont); }
// 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; }
/** * 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 any non-isolated vertex; -1 if no such vertex private static int nonIsolatedVertex(Digraph G) { for (int v = 0; v < G.V(); v++) if (G.outdegree(v) > 0) return v; return -1; }