template <typename Graph>
class FindCycleDFS : public DFS<Graph> {
protected: // local types
typedef typename Graph::Vertex Vertex;
typedef typename Graph::Edge Edge;
// ... (other Graph typenames omitted)
private: // local data
bool cycleDetected; // cycle detected?
Vertex cycleStart; // start of cycle
EdgeSequence cycle; // cycle storage
protected: // overrriden functions
virtual void finishVisit(const Vertex& v) { // finished with vertex
if ((!cycle.isEmpty()) && (!cycleDetected)) // not building a cycle?
cycle.remove(cycle.last()); // remove this edge
}
virtual void traverseDiscovery(const Edge& e, const Vertex& from)
{ if (!cycleDetected) cycle.insertLast(e); } // add edge to sequence
virtual void traverseBack(const Edge& e, const Vertex& from) {
if (!cycleDetected) { // no cycle yet?
cycleDetected = true; // cycle is now detected
cycle.insertLast(e); // insert back edge
cycleStart = G.opposite(from, e); // save starting vertex
}
}
virtual bool isDone() const { return cycleDetected; } // done yet?
public:
FindCycleDFS(const Graph& g) : DFS<Graph>(g) { } // constructor
EdgeSequence run(const Vertex& s) { // find a cycle from s
initialize(); // initialize DFS
cycle = EdgeSequence(); // create cycle sequence
cycleDetected = false;
dfsTraversal(s); // do the search
if (!cycle.isEmpty() && s != cycleStart) { // found a cycle?
EdgeSeqPosIterator pi = cycle.positions();
while (pi.hasNext()) { // remove the tail
EdgeSeqPosition ep = pi.next();
cycle.remove(ep); // ...up to cycleStart
if (G.areIncident(cycleStart, ep.element())) break;
}
}
return cycle; // return the cycle
}
};