Thursday, July 13th

Courses with pre-requisites.  Given prerequisite requirements, can all courses be taken?  We are given a directed edgelist where a node from u to v means to take course u, you must first take node u.

A collection of courses cannot be completed when there's cyclic dependencies.  This problem is the same as yesterday's.  We will use topological sort to find cycles.

First we reverse the graph.  For topological sort, we want to start with nodes that have no incoming edges.  This means we reverse the graph so an edge v to u means v must be taken before u.  We will create an adjacency list to represent the reversed graph

       vector<vector<int> > adjlist(numCourses);
int u,v;
for(int i=0; i<prerequisites.size(); i++) {
u=prerequisites[i][0];
v=prerequisites[i][1];
adjlist[v].push_back(u);
}

Next we calculate the indegree for each vertex.  This is accomplished by iterating over the adjacency list, and incrementing a node's indegree whenever the node appears in the adjacency list

        vector<int> indegree(numCourses, 0);
vector<int> adj;
for(int i=0; i<numCourses; i++) {
adj=adjlist[i];
for(int j=0; j<adj.size(); j++) {
v=adj[j];
indegree[v]+=1;
}
}

We want to begin topological sort using nodes with indegree of zero, so iterate through the indegree vector and push nodes with 0 indegree

        queue<int> q;      
for(int i=0; i<numCourses; i++) {
if(indegree[i]==0) {
q.push(i);
}
}

Finally, we perform breadth first search using the queue of nodes with 0 indegree.  We count each time a node is popped from the queue.  Every time a node is popped, we iterate over its neighbors and decrement each neighbor's indegree by 1.  If the new indegree is 0, it's added to the back of the queue.  Like breadth-first search, this process continues until the queue is empty.

        int node, numdone=0, qsize, neighbor;
vector<int> neighbors;
while(!q.empty()) {
qsize=q.size();
for(int i=0; i<qsize; i++) {
node = q.front();
q.pop();
numdone++;
neighbors = adjlist[node];
for(int j=0; j<neighbors.size(); j++) {
neighbor=neighbors[j];
indegree[neighbor]-=1;
if(indegree[neighbor]==0) {
q.push(neighbor);
}
}
}
}

Counting the number of processed ("popped") nodes, if the number processed equals the total number of nodes in the original graph, then we can finish all the courses.  If the number of processed nodes is less than the total number of nodes, then we have a cycle, and the courses cannot be finished

return numdone == numCourses ? true : false;

Thanks to the cycle problem yesterday for a primer on topological sort

Comments

Popular posts from this blog

Wednesday, September 20th

Monday, September 11th

Tuesday, September 19th