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.
解法一(BFS):
class Solution {
public:
bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
vector<unordered_set<int>> graph = make_graph(numCourses, prerequisites);
vector<int> indegree = compute_indegree(graph);
for(int i = 0; i<numCourses; i++){
int j = 0;
for(; j<numCourses; j++)
if(indegree[j] == 0)
break;
if(j == numCourses) return false;
indegree[j] = -1;
for(int neigh: graph[j])
indegree[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.first].insert(pre.second);
return graph;
}
vector<int> compute_indegree(vector<unordered_set<int>> graph) {
vector<int> indegree(graph.size(), 0);
for(auto neighbors: graph)
for(int neigh: neighbors)
indegree[neigh]++;
return indegree;
}
};
入度为0的结点也可以用栈或队列维护,用一个计数变量判断到底有多少个结点可以出队。
解法二(DFS):
class Solution {
public:
bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
vector<unordered_set<int>> graph = make_graph(numCourses, prerequisites);
vector<bool> visited(numCourses, false), onpath(numCourses, false);
for(int i = 0; i<numCourses; i++)
if(!visited[i] && dfs_cycle(graph, i, visited, onpath))
return false;
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.first].insert(pre.second);
return graph;
}
bool dfs_cycle(vector<unordered_set<int>>& graph, int node, vector<bool>& visited, vector<bool>& onpath) {
if(visited[node]) return false;
onpath[node] = visited[node] = true;
for(int neigh: graph[node])
if(onpath[neigh] || dfs_cycle(graph, neigh, visited, onpath))
return true;
onpath[node] = false;
return false;
}
};
维护了两个标志数组,一个是全局的,一个是本路径的。
详细解析参考:
https://leetcode.com/problems/course-schedule/discuss/58509/18-22-lines-C++-BFSDFS-Solutions
附:
拓扑排序的算法(DFS):
https://www.geeksforgeeks.org/topological-sorting/