import java.util.Scanner; import java.io.File; import java.io.IOException; import java.util.Arrays; /* Java application having as its purpose to test the CycleFinder class. ** It creates a digraph (i.e., an instance of the Digraph class) using ** the data in a file whose name is provided either as a command line ** argument or by the user in response to a prompt. Then it has the ** user enter one or more target vertex IDs, in response to which it uses ** an instance of CycleFinder to find, for each such vertex, a shortest ** cycle on which it lies (if any). */ public class CycleFinderTester { private static Scanner keyboard = new Scanner(System.in); public static void main(String[] args) throws IOException { Scanner graphInput; String fileName; if (args.length != 0) { fileName = args[0]; } else { System.out.print("Enter name of input file: "); fileName = keyboard.nextLine(); } graphInput = new Scanner(new File(fileName)); Digraph graph = buildGraph(graphInput); graph.printDescription(); CycleFinder pf = new CycleFinder(); final int N = graph.numVertices(); // Now have user repeatedly request info about shortest cycles. boolean keepGoing = true; while (keepGoing) { System.out.print("\nEnter ID of target vertex: "); int target = keyboard.nextInt(); // If the user entered -1, a description of the digraph is printed. // If the user entered a value less than -1, the program terminates. if (target == -1) { graph.printDescription(); } else if (target < -1) { keepGoing = false; } else { pf.findShortestCycle(graph, target); printReport(pf); } } System.out.println("Goodbye."); } private static void printReport(CycleFinder pf) { int targetID = pf.targetVertex(); if (!pf.cycleExists()) { System.out.printf("Vertex %d does not lie on a cycle.\n", targetID); } else { System.out.printf("Shortest cycles involving vertex %d have length %d\n", targetID, pf.length()); // System.out.println("One shortest cycle: " + // Arrays.toString(pf.cycle())); System.out.print("One shortest cycle: "); pf.printCycle(); System.out.println(); } } /* Returns a new Digraph object as described by the source of data to ** which the given Scanner is attached. The expected format of the ** graph's description is that the first line contains an integer N ** providing the number of vertices in the graph. The remaining input ** is on the next N lines, the k-th of which contains a list of IDs ** of the vertices to which vertex k-1 has an edge. Any non-integer ** data on a line is taken to indicate the end of the meaningful data ** on that line. ** Example: ** +------------------------------------------------------ ** |4 // number of vertices ** |2 3 // vertex 0 has outgoing edges to vertices 2 and 3 ** |0 // vertex 1 has an outgoing edge to vertex 0 ** | // vertex 2 has no outgoing edges ** |2 0 1 // vertex 3 has outgoing edges to vertices 2, 0, and 1 ** +------------------------------------------------------ */ private static Digraph buildGraph(Scanner input) { int numVertices = input.nextInt(); input.nextLine(); Digraph graph = new Digraph(numVertices); for (int i = 0; i != numVertices; i++) { Scanner edgeScanner = new Scanner(input.nextLine()); while (edgeScanner.hasNextInt()) { int j = edgeScanner.nextInt(); graph.addEdge(i,j); } } return graph; } }