// Chooses the correct edge to follow given possible options in the cycle joining phase int Graph::selectEdge(std::vector<int> & connections) { std::vector<int> firstPri; std::vector<int> secondPri; std::vector<int> thirdPri; for(auto&& edgeIndex : connections) { auto edge = edges[edgeIndex]; if (!inStack(edge.cycleID)) { firstPri.push_back(edgeIndex); // First priority: Return unused edge from a new cycle } if (edge.cycleID == cycleStack.end()[-1]) { secondPri.push_back(edgeIndex); // Second priority: Return unused edge from current cycle } if (edge.cycleID == cycleStack.end()[-2]) { thirdPri.push_back(edgeIndex); // Third priority: Return unused edge from previous cycle } } if (!firstPri.empty()) return firstPri[0]; else if (!secondPri.empty()) return secondPri[0]; else if (!thirdPri.empty()) return thirdPri[0]; output << "CRITICAL FAILURE :(" << std::endl; return -1; }
// Manages the cycle stack void Graph::updateCycle(int edgeIndex, int toNode) { auto edge = edges[edgeIndex]; int fromNode = edge.getOtherEndpoint(toNode); if (!inStack(edge.cycleID)) // if current cycle is not on the stack { cycleStack.push_back(edge.cycleID); cycleStartNodes[edge.cycleID] = fromNode; } if (toNode == cycleStartNodes[edge.cycleID]) // If the cycle is finished { cycleStack.pop_back(); } }
bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) { if (prerequisites.empty() || numCourses == 0) return true; // build adjacency list vector<unordered_set<int>> adj(numCourses); for (int i = 0; i < prerequisites.size(); i++) { // e.second -> e.first, i.e. e.second is a prerequisite for e.first pair<int, int> e = prerequisites[i]; adj[e.second].insert(e.first); } // detect directed cycle in adj vector<bool> visited(numCourses, false); vector<bool> inStack(numCourses, false); for (int i = 0; i < numCourses; i++) { if (!visited[i]) { if (dfs(adj, i, visited, inStack)) { // a cycle exists: cannot finish return false; } } } // no cycle detected: can finish return true; }