import java.util.Iterator; import java.util.Arrays; /* CycleFinder.java ** An instance of this class is for the purpose of finding shortest cycles ** in directed graphs. The intent is that the client will invoke the ** findShortestCycle() method (which finds --if it exists-- a shortest cycle ** beginning at a specified vertex within a given directed graph) and then call ** one or more of the observer methods in order to gather information about ** the cycle that was discovered (if one exists). ** ** Authors: R. McCloskey and < STUDENT'S NAME > ** Date: March 2020 ** Collaborated with: ... ** Known Defects: ... */ public class CycleFinder { // instance variables // ------------------ // The values of the instance variables are all with respect to the cycle // discovered (if any) by the most recent call to the findShortestCycle() // method, which finds a shortest cycle beginning at a specified "target" // vertex (if such a cycle exists). protected int target; // ID of the target vertex protected boolean cycleFound; // Does the target vertex lie on a cycle? protected int[] pred; // pred[w] = -1 means that w does not lie on the // cycle that was discovered (if any). // pred[w] == v (v >= 0) means that, if w lies on the // discovered cycle, (v,w) is an edge on that cycle, // which is to say that v is the predecessor of w // on that cycle. // observers // --------- // The values returned by the observer methods are all with respect // to the cycle discovered (if any) by the most recent call to the // findShortestCycle() method. /* Returns the ID of the target vertex. */ public int targetVertex() { return target; } /* Reports whether or not a cycle was discovered. */ public boolean cycleExists() { return cycleFound; } /* Returns the length of (i.e., # of edges in) the discovered cycle ** (or -1 if no such cycle exists). */ public int length() { int cntr = -1; if (cycleFound) { cntr = 1; int w = pred[target]; while (w != target) { w = pred[w]; cntr++; } } return cntr; } /* Returns an array containing the IDs of vertices on the discovered cycle ** (in the order that they would be visited along the cycle, starting and ** ending with the target vertex). If there is no such cycle, the returned ** array has length zero. */ public int[] cycle() { int cycleLen = length(); int[] result = new int[cycleLen+1]; // MISSING CODE GOES HERE return result; } /* Prints the IDs of the vertices on the discovered cycle (in the order ** that they would be visited along the cycle, starting and ending with ** the target vertex). If there is no such cycle, nothing is printed. */ public void printCycle() { System.out.print(Arrays.toString(cycle())); } // mutator // ------- /* Finds a shortest cycle beginning at vertex v in the given digraph ** (if such a cycle exists) so that subsequent calls to the observers ** will yield information about that cycle. */ public void findShortestCycle(Digraph graph, int v) { target = v; final int N = graph.numVertices(); pred = new int[N]; fill(pred, -1); // Place -1 in every element of pred[] cycleFound = false; // Create the queue and prime it by inserting the target vertex. Queue q = new QueueViaArray(); q.enqueue(v); // Loop needed here to "explore" from each vertex in the queue, // causing "discovered" vertices to be placed in the queue so that // exploration from them will occur later. // This breadth-first search should terminate when (and if) the // target vertex is discovered. Along the way, relevant data // is placed into the pred[] array to make it possible for the // length() and cycle() methods to traverse the path easily. // MISSING CODE GOES HERE! } // utilities // --------- /* Places the specified value into every element of the specified array. */ private void fill(int[] a, int val) { for (int i=0; i != a.length; i++) { a[i] = val; } } }