类别:graph(拓扑)
难度:medium
题目描述
There are a total of n courses you have to take, labeled from 0
to n - 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.
算法分析
(1)利用题目给的边,将每个点的后继节点存储起来
(2)计算每个节点的入度
(3)对于入度为0的课程先修,然后将其后继节点的入度减去1
代码实现
class Solution {
public:
// 需要保证构造出来的图没有环
bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
// 首先,计算每一门课程的后继课程
vector<unordered_set<int> > childs(numCourses);
for (int i = 0; i < prerequisites.size(); ++i) {
childs[prerequisites[i].second].insert(prerequisites[i].first);
}
// 计算每一门课程的入度
vector<int> degree(numCourses, 0);
for (int i = 0; i < numCourses; ++i) {
for (auto it = childs[i].begin(); it != childs[i].end(); ++it) {
degree[*it]++;
}
}
// 先将入度为0的课程修完
int k = 0;
for (int i = 0; i < numCourses; ++i) {
// 外层循环判断了n门入度为0的课程,如果是每一门课程都能够修的话,最后应该刚好是n门入度为0的课程
// 所以在内层循环中总是能够找到入度为0的课程
for (k = 0; k < numCourses && degree[k] != 0; ++k);
if (k == numCourses) return false;
for (auto it = childs[k].begin(); it != childs[k].end(); ++it) {
degree[*it]--;
}
degree[k]=-1;
}
return true;
}
};