你这个学期必须选修 numCourses
门课程,记为 0
到 numCourses - 1
。
在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites
给出,其中 prerequisites[i] = [ai, bi]
,表示如果要学习课程 ai
则 必须 先学习课程 bi
。
- 例如,先修课程对
[0, 1]
表示:想要学习课程0
,你需要先完成课程1
。
请你判断是否可能完成所有课程的学习?如果可以,返回 true
;否则,返回 false
。
、
示例 1:
代码语言:javascript复制输入:numCourses = 2, prerequisites = [[1,0]]
输出:true
解释:总共有 2 门课程。学习课程 1 之前,你需要完成课程 0 。这是可能的。
示例 2:
代码语言:javascript复制输入:numCourses = 2, prerequisites = [[1,0],[0,1]]
输出:false
解释:总共有 2 门课程。学习课程 1 之前,你需要先完成课程 0 ;并且学习课程 0 之前,你还应先完成课程 1 。这是不可能的。
代码语言:javascript复制class Solution {
public:
//判断拓扑排序
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
vector<vector<int>> eages(numCourses); //n个头结点
queue<int> q; //存入度为0的点
vector<int> d(numCourses); //存每个序号的入度
//初始化邻接表
for(auto& v : prerequisites){
int a = v[0], b = v[1];
eages[b].push_back(a); // b --> a
d[a] ;
}
//将入度为0的点入队
for(int i = 0; i < numCourses; i ) {
if(!d[i]) q.push(i);
}
int cnt = 0; //存当前输出的节点个数
//开始topsort
while(!q.empty()){
auto t = q.front(); q.pop();
cnt ;
//将所有t能指向的点的入度--,相当于删去了当前节点
for(int c : eages[t]){
d[c]--;
if(!d[c]) q.push(c); //如果入度-1后为0,则说明可以作为下一个待输出的节点,入队
}
}
return cnt == numCourses;
}
};