题目:要修n门课程,修某些课程会有先决条件(要已经修完某门课程)要求判断能否修完所有课程。
链接:https://leetcode.com/problems/course-schedule/
算法思路:
用有向图表示课程和课程间的关系,比如修课程b之前需要修完课程a,则表示为结点a有一条指向结点b的边,即<a,b>
那么要求判断能否修完所有课程就转化成判断有向图中是否存在环。
然后用BFS算法解决。首先去找入度为0的结点,若不存在该结点,说明存在环。若找到,则把它的入度设为-1表示已访问,然后去访问它的邻接点,对每个邻接点的入度减1。重复上述步骤n遍。
代码如下:
class Solution {
public:
bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
vector<unordered_set<int>> graph = make_graph(numCourses, prerequisites);
vector<int> degrees = compute_indegree(graph);
for (int i = 0; i < numCourses; i++) {
int j = 0;
for (; j < numCourses; j++)
if (!degrees[j]) break;
if (j == numCourses) return false;
degrees[j] = -1;
for (int neigh : graph[j])
degrees[neigh]--;
}
return true;
}
private:
vector<unordered_set<int>> make_graph(int numCourses, vector<pair<int, int>>& prerequisites) {
vector<unordered_set<int>> graph(numCourses);
for (auto pre : prerequisites)
graph[pre.second].insert(pre.first);
return graph;
}
vector<int> compute_indegree(vector<unordered_set<int>>& graph) {
vector<int> degrees(graph.size(), 0);
for (auto neighbors : graph)
for (int neigh : neighbors)
degrees[neigh]++;
return degrees;
}
};