课程表(深度优先遍历/拓扑排序)
你这个学期必须选修 numCourses 门课程,记为 0 到 numCourses - 1 。
在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出,其中 prerequisites[i] = [ai, bi] ,表示如果要学习课程 ai 则 必须 先学习课程 bi 。
- 例如,先修课程对
[0, 1]表示:想要学习课程0,你需要先完成课程1。
请你判断是否可能完成所有课程的学习?如果可以,返回 true ;否则,返回 false 。
示例 1:
输入:numCourses = 2, prerequisites = [[1,0]] 输出:true 解释:总共有 2 门课程。学习课程 1 之前,你需要完成课程 0 。这是可能的。
示例 2:
输入:numCourses = 2, prerequisites = [[1,0],[0,1]] 输出:false 解释:总共有 2 门课程。学习课程 1 之前,你需要先完成课程 0 ;并且学习课程 0 之前,你还应先完成课程 1 。这是不可能的。
class Solution { public: vector<vector<int>> edge; vector<int> visit; bool isVaild = true; bool canFinish(int numCourses, vector<vector<int>>& prerequisites) { edge.resize(numCourses); visit.resize(numCourses); int n = prerequisites.size(); //初始化边集 for(int i=0;i<n;i++){ //学prerequisites[i][0]之前要先学prerequisites[i][1], //所以prerequisites[i][1]指向prerequisites[i][0] edge[prerequisites[i][1]].push_back(prerequisites[i][0]); } for(int i=0;i<numCourses&&isVaild;i++){ if(visit[i]==0){//如果是未搜索的科目,则深搜 dfs(i); } } return isVaild; } void dfs(int v){ visit[v] =1 ;//首先标记该节点为搜索中,即相邻的节点没有搜索完成 vector<int> pre = edge[v];//后修课程 for(int i=0;i<pre.size();i++){ //遍历其后修学科 int w = pre[i]; if(visit[w]==0){//如果未搜索过,则深搜 dfs(w); if(!isVaild){//有环 return; } }else if(visit[w]==1){//如果为搜索中,则有环,不存在拓扑排序的; isVaild = false; return; } } visit[v]=2;//标记该节点为搜索完成,即该节点已经入栈,并且所有该节点的相邻节点都出现在栈的更底部的位置,满足拓扑排序的要求 } };
浙公网安备 33010602011771号