题意: 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.
Note:
The input prerequisites is a graph represented by a list of edges, not adjacency matrices. Read more about how a graph is represented.
You may assume that there are no duplicate edges in the input prerequisites.
click to show more hints.
Hints:
This problem is equivalent to finding if a cycle exists in a directed graph. If a cycle exists, no topological ordering exists and therefore it will be impossible to take all courses.
Topological Sort via DFS - A great video tutorial (21 minutes) on Coursera explaining the basic concepts of Topological Sort.
Topological sort could also be done via BFS.
思路:这题的主要目的是判断有向图中是否存在环,可以使用拓扑排序 的方法解决这道题,拓扑排序是用BFS的方法解决的,当然也可以使用DFS来检查是否存在环,先放python的使用拓扑排序的代码:
class Solution(object):
def canFinish(self, numCourses, prerequisites):
"""
:type numCourses: int
:type prerequisites: List[List[int]]
:rtype: bool
"""
edge = {i:[] for i in xrange(numCourses)}
for i in xrange(len(prerequisites)):
edge[prerequisites[i][0]].append(prerequisites[i][1])
indegree = [0] * numCourses
for i in edge:
for j in edge[i]:
indegree[j] += 1
stack = []
for i in xrange(numCourses):
if indegree[i] == 0:
stack.append(i)
count = 0
while stack:
cur = stack.pop()
count += 1
for i in edge[cur]:
indegree[i] -= 1
if indegree[i] == 0:
stack.append(i)
return False if count < numCourses else True
还有一段使用dfs的c++的代码:
class Solution {
public:
bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
vector<unordered_set<int>> edge(numCourses);
vector<bool> visited(numCourses,false);
for (auto pre:prerequisites)
edge[pre.first].insert(pre.second);
for (int i = 0;i<numCourses;i++){
if(!dfs(edge,visited,i))
return false;
}
return true;
}
private:
bool dfs(vector<unordered_set<int>> &edge,vector<bool> &visited,int node){
if (visited[node])
return false;
else
visited[node] = true;
for (auto it = edge[node].begin();it!=edge[node].end();it++){
if(!dfs(edge,visited,*it))
return false;
}
visited[node] = false;
return true;
}
};
这里有个很关键的是visited[node] = false,意思很明确,比如有两条分叉路的时候,一条已经判断无环了,则分叉点visited又要置为0,让另一条分叉路得以继续判断。