207. Course Schedule
There are a total of n courses you have to take, labeled from
0
ton - 1
.
Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]
Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses?
For example:
2, [[1,0]]
There are a total of 2 courses to take. To take course 1 you should have finished course 0. So it is possible.
2, [[1,0],[0,1]]
There are a total of 2 courses to take. To take course 1 you should have finished course 0, and to take course 0 you should also have finished course 1. So it is impossible.
题目大意
前提:有部分课程需要以另一门课程为前提,如果存在两门课互为前提,则该课程信息不可完成;如果不存在,则该课程信息可完成。
输入课程信息,判断该课程信息能否完成。
解题思路
这是一个拓扑排序问题。
遍历有向图中的节点,每次找到一个入度为0的节点,将其push进队列。然后利用BFS,取队列的头(并将其pop掉),将该节点所指向其他节点的边都去掉(即,将其指向的节点入度减一),如果存在节点入度减一的值为零,则将其push入队列,重复这个过程,直到队列为空。
最后检查送队列中被pop掉的节点总数,如果总数等于课程数量,则说明该有向图无环,课程信息可完成;如果总数小于课程数量,则说明该有向图存在环,课程信息不可完成。
算法复杂度
O(|V+E|)
代码实现
class Solution {
public:
bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
vector<int> inDegreeMap(numCourses);
vector<pair<int,int>>::iterator iter;
// compute the in-degree of all points
for (iter = prerequisites.begin(); iter != prerequisites.end(); iter++) {
++inDegreeMap[iter->second];
}
// push back the 0-inDegree point to the queue
queue<int> que;
for (int i = 0; i < numCourses; ++i) {
if (inDegreeMap[i] == 0) { que.push(i); }
}
// BFS
int count = que.size();
while (!que.empty()) {
int u = que.front();
que.pop();
for (iter = prerequisites.begin(); iter != prerequisites.end(); iter++) {
if (u == iter->first) {
// find the next position of u
// and determine whether its (in-degree - 1) equals 0
int uLast = iter->second;
if (--inDegreeMap[uLast] == 0) {
que.push(uLast);
++count;
}
}
}
}
return count == numCourses;
}
};