int getNumComponents(graph &g) { g.clearMark(); g.clearVisit(); int numComponents = 0; queue<int> currentMoves; for (int n=0;n<g.numNodes();n++) { if (!g.isVisited(n)) { numComponents++; int nodeNumber=n; g.visit(nodeNumber); currentMoves.push(nodeNumber); while(currentMoves.size() > 0) { int currentNode = currentMoves.front(); currentMoves.pop(); //Populate a list of nodes that can be visited for (int i=0;i<g.numNodes();i++) { if (g.isEdge(currentNode,i) && !g.isVisited(i)) { g.mark(currentNode,i); g.visit(i); currentMoves.push(i); } } } } } return numComponents; }
bool isConnected(graph &g) // Returns true if the graph g is connected. Otherwise returns false. { queue<int> que; int id=0,count=1; que.push(id); g.visit(id); while(count<g.numNodes() && !que.empty()) { id=que.front(); for(int i=0;i<g.numNodes();i++) { if (g.isEdge(id,i) && !g.isVisited(i)) { g.visit(i); que.push(i); count++; } } que.pop(); } for (int z=0;z<g.numNodes();z++) g.unVisit(z); if(count==g.numNodes()) return true; else return false; }
void findMSF(graph &g, graph &sf, int start) // finds a minimum spanning tree in graph 'g' { priority_queue<edge, vector<edge>, CompareEdge> pq; vector<int> lst = getNeighbors(start, g); // build our priority queue for (int i = 0; i < lst.size(); i++) { pq.push(g.getEdge(start, lst[i])); g.mark(start, lst[i]); } // visit the start node g.visit(start); int src, dst, w; edge top; while (!pq.empty()) { top = pq.top(); pq.pop(); src = top.getSource(); dst = top.getDest(); w = top.getWeight(); // add edges if (!sf.isEdge(src, dst)) { sf.addEdge(src, dst, w); sf.addEdge(dst, src, w); // delete edges if we make a cycle if (isCyclic(sf)) { sf.removeEdge(src, dst); sf.removeEdge(dst, src); } else { g.visit(src); lst = getNeighbors(dst, g); for (int i = 0; i < lst.size(); i++) { if (!g.isMarked(dst, lst[i])) { pq.push(g.getEdge(dst, lst[i])); g.mark(dst, lst[i]); } } // for } // else } // if } // while } // findMSF
bool isCyclic(graph &g) // Returns true if the graph g contains a cycle. Otherwise, returns false. { queue<int> que; int id=0,count=1; bool first=true; vector<int> parentCount(g.numNodes(),-1); que.push(id); g.visit(id); while(count<g.numNodes() || !que.empty()) { if (que.empty()) { id=count; que.push(id); g.visit(id); count++; } else id=que.front(); for(int i=0;i<g.numNodes();i++) { if (g.isEdge(id,i) && i!=que.front()) { if(!g.isVisited(i)) { g.visit(i); que.push(i); count++; parentCount[i]=id; } else if(parentCount[id]==i) continue; else { for (int z=0;z<g.numNodes();z++) g.unVisit(z); return true; } } } que.pop(); } for (int z=0;z<g.numNodes();z++) g.unVisit(z); return false; }
void findCycle(int curr, int start, bool &found, graph &g) // checks for cycles in a graph { g.mark(curr); vector<int> lst = getNeighbors(curr, g); for (int i = 0; i < lst.size(); i++) { if (start == lst[i]) { continue; } if (g.isMarked(lst[i])) { found = true; } else if (!g.isVisited(lst[i])) { findCycle(lst[i], curr, found, g); } } // for g.unMark(curr); g.visit(curr); } // findCycle
void recursiveDFS(int curId, int dstId, graph &g, stack<int> &path, bool &done) // depth first search that uses the mem stack to search the graph g { if (curId == dstId) { done = true; path.push(curId); } else { g.mark(curId); g.visit(curId); vector<int> lst = getNeighbors(curId, g); while (!lst.empty()) { int current = lst.back(); lst.pop_back(); if (!g.isVisited(current)) { recursiveDFS(current, dstId, g, path, done); } if (done) // if we found our node then construct our path { path.push(curId); break; } } } }
bool dfsCyclic(graph &g, int current, int prev) // depth first search to find cycles in graph // first removes the preceeding node from vector of neighbors // then if there is a visited node neighbor, there is a cycle // returns true for there is a cycle, otherwise false { g.visit(current); vector<int> neighbors = getNeighbors(g, current); // remove prev from neighbors // make sure neighbors is not empty so we dont erase from empty vector if (prev != NONE && !neighbors.empty()) { int index = 0; for (int k = 0; k < (int) neighbors.size(); k++) { if (neighbors[k] == prev) index = k; } // at some index, it is the (index + 1)th element // so just have to do .begin() + index neighbors.erase(neighbors.begin() + index); } for (int i = 0; i < (int) neighbors.size(); i++) { if (g.isVisited(neighbors[i])) return true; else if (dfsCyclic(g, neighbors[i], current)) return true; } return false; // ran through all neighbors and no cycles }
void findSpanningForest(graph &g, graph &sf) // Create a graph sf that contains a spanning forest on the graph g. { queue<int> que; int id=0,count=1; bool first=true; vector<int> parentCount(g.numNodes(),-1); que.push(id); g.visit(id); while(count<g.numNodes() || !que.empty()) { if (que.empty()) { id=count; que.push(id); g.visit(id); count++; } else id=que.front(); for(int i=0;i<g.numNodes();i++) { if (g.isEdge(id,i) && i!=que.front()) { if(!g.isVisited(i) && parentCount[id]!=i) { g.visit(i); sf.addEdge(id,i,g.getEdgeWeight(i,id)); sf.addEdge(i,id,g.getEdgeWeight(i,id)); que.push(i); count++; parentCount[id]++; } } } que.pop(); } for (int z=0;z<g.numNodes();z++) g.unVisit(z); }
void dfs(graph &g, int current) // generic depth first search traversal { g.visit(current); vector<int> neighbors = getNeighbors(g, current); for (int i = 0; i < (int) neighbors.size(); i++) { if (!g.isVisited(neighbors[i])) dfs(g, neighbors[i]); } }
void kruskal(graph &g, graph &sf) // Given a weighted graph g, sets sf equal to a minimum spanning // forest on g. Uses Kruskal's algorithm. { g.clearMark(); g.clearVisit(); numComponents=0; while(!g.allNodesVisited()) { // find the smallest edge int smallestEdgeWeight = -1; int smallestEdgeBeg = -1; int smallestEdgeEnd = -1; for(int i = 0; i < g.numNodes(); i++) { for(int j = 0; j < g.numNodes(); j++) { if(g.isEdge(i, j) && !g.isVisited(i, j) && !g.isVisited(j, i) && (!g.isVisited(i) || !g.isVisited(j))) { if(g.getEdgeWeight(i, j) < smallestEdgeWeight || smallestEdgeWeight == -1) { smallestEdgeWeight = g.getEdgeWeight(i, j); smallestEdgeBeg = i; smallestEdgeEnd = j; } } } } // add the new edge g.visit(smallestEdgeBeg); g.visit(smallestEdgeEnd); g.visit(smallestEdgeBeg, smallestEdgeEnd); sf.addEdge(smallestEdgeBeg, smallestEdgeEnd); sf.setEdgeWeight(smallestEdgeBeg, smallestEdgeEnd, smallestEdgeWeight); } numComponents = getNumComponents(sf); }
void prim(graph &g, graph &sf) // Given a weighted graph g, sets sf equal to a minimum spanning // forest on g. Uses Prim's algorithm. { g.clearMark(); g.clearVisit(); numComponents=0; int currentNode = 0; while(!g.allNodesVisited()) { // find next currentNode while(g.isVisited(currentNode) && currentNode < g.numNodes()) { currentNode++; } g.visit(currentNode); int smallestEdgeWeight = -1; int smallestEdgeNode = -1; // find shortest new edge from currentNode for(int i = 0; i < g.numNodes(); i++) { if(g.isEdge(currentNode, i)) { if(g.getEdgeWeight(currentNode, i) < smallestEdgeWeight || smallestEdgeWeight == -1) { smallestEdgeWeight = g.getEdgeWeight(currentNode, i); smallestEdgeNode = i; } } } // add the new edge g.visit(smallestEdgeNode); sf.addEdge(currentNode, smallestEdgeNode); sf.setEdgeWeight(currentNode, smallestEdgeNode, smallestEdgeWeight); } numComponents = getNumComponents(sf); }
void dfsAddEdges(graph &g, int current, graph &sf) // depth first search to visit all nodes and add edges to unvisited nodes { g.visit(current); vector<int> neighbors = getNeighbors(g, current); for (int i = 0; i < (int) neighbors.size(); i++) { if (!g.isVisited(neighbors[i])) { sf.addEdge(current, neighbors[i], g.getEdgeWeight(current, neighbors[i])); sf.addEdge(neighbors[i], current, g.getEdgeWeight(neighbors[i], current)); dfsAddEdges(g, neighbors[i], sf); } } }
void findSpanningForest(graph &g, graph &sf) // Create a graph sf that contains a spanning forest on the graph g. { g.clearMark(); g.clearVisit(); numComponents=0; queue<int> currentMoves; for (int n=0;n<g.numNodes();n++) { if (!g.isVisited(n)) { numComponents++; int nodeNumber=n; g.visit(nodeNumber); currentMoves.push(nodeNumber); while(currentMoves.size() > 0) { int currentNode = currentMoves.front(); currentMoves.pop(); //Populate a list of nodes that can be visited for (int i=0;i<g.numNodes();i++) { if (g.isEdge(currentNode,i) && !g.isVisited(i)) { g.mark(currentNode,i); sf.addEdge(currentNode,i); sf.setEdgeWeight(currentNode, i, g.getEdgeWeight(currentNode, i)); g.visit(i); currentMoves.push(i); } } } } } }
bool isCyclic(graph &g,int nodeNumber) // Returns true if the graph g contains a cycle. Otherwise, returns false. { if (g.isVisited(nodeNumber)) { return true; } //Visit the node g.visit(nodeNumber); for (int i=0;i<g.numNodes();i++) { if (g.isEdge(nodeNumber,i)) { return isCyclic(g,i); } } return false; }
vector<stack<int> > nonRecursiveDFS(int startId, int dstId, graph &g ) // implement a version of Depth First Search that uses a stack data structure // and does not use recursion returns all paths { vector< stack<int> > paths; stack<int> st; stack<edge> edges; st.push(startId); stack<int> path; while (!st.empty()) { int top = st.top(); //check if before we had gone into a sink and remove from path while (!edges.empty() && path.top() != edges.top().getSource()) { path.pop(); } path.push(top); if (!edges.empty()) { edges.pop(); } st.pop(); g.visit(top); if (top == dstId) { paths.push_back(path); } vector<int> lst = getNeighbors(top, g); for (int i = 0; i < lst.size(); i++) { if (!g.isVisited(lst[i])) { st.push(lst[i]); edges.push(g.getEdge(top, lst[i])); } } } return paths; }
stack<int> nonRecursiveBFS(int startId, int dstId, graph &g ) // implement a version of Breadth First Search that uses a stack data structure // and does not use recursion and returns the first path found { queue<int> q; stack<int> path; map<int, int> edges; q.push(startId); bool found = false; while (!q.empty()) { int top = q.front(); q.pop(); if (top == dstId) { found = true; path.push(dstId); break; } g.visit(top); vector<int> lst = getNeighbors(top, g); for (int i = 0; i < lst.size(); i++) { if (!g.isVisited(lst[i])) { q.push(lst[i]); edges.insert( pair<int, int>(lst[i], top) ); } } } // start backtracking int current = dstId; while (found && current != startId) { current = edges.find(current)->second; path.push(current); } return path; }
// Helper Functions void visitNodes(int start, graph &g) // Visit all nodes reachable from the start node { bool found = false; // Mark the start node as visited. g.visit(start); int v = 0; // Keep looking for legal moves as long as there are more neighbors // to check. while (!found && v < g.numNodes()) { // if v is an unvisited neighbor of the start node, recurse. if (g.isEdge(start, v) && !g.isVisited(v)) { visitNodes(v, g); } v++; } } // visitNodes