题意理解
有n个课程,两两课程之间有前置关系,上这个课必须要先上另外一个课。问能不能上完所有课?
问题分析
图论,DFS遍历。
图的结构表示,用vector<vector<int>> graph,邻接表表示。
DFS的算法结构
分两部分
第一部分:设置访问数组vector<int> visited(nums, 0),初值置为0.一个循环遍历所有结点,如果没有访问过,执行DFS;
第二部分:DFS设计,参数是遍历的开始结点,图,访问数组,是否是环,共4个参数,最后一个是遍历的目的。DFS设计的方式是如果被访问过,返回,如果没有,先设置为访问过。然后遍历它的邻接点,每个邻接点递归调用dfs;然后设置当前结点访问结束。
其他
链接
bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
vector<vector<int>> graph(numCourses);
for(int i = 0; i < prerequisites.size(); i++) //构建图
{
graph[ prerequisites[i]. second ].push_back( prerequisites[i]. first );
}
vector<int> visited(numCourses, 0); //初始化访问数组
bool isCycle = false; //环标记
for(int i = 0; i < numCourses; i ++) //遍历图结点
{
if (isCycle) return false; //如果有环,返回失败
if(visited[i] == 0) helper(i, graph, visited, isCycle); //如果没有访问,深度遍历,结果保存在最后一个参数中
}
return !isCycle;
}
void helper(int i, vector<vector<int>>& graph, vector<int>& visited, bool& isCycle)
{
if (visited[i] == 1) //如果访问过,说明出现环
{
isCycle = 1; //标记环
return; //返回
}
visited[i] = 1; //标记当前结点为访问过
for(int j = 0; j < graph[i].size(); j ++) //遍历邻接点
{
helper(graph[i][j], graph, visited, isCycle); //对每个邻接点递归调用dfs算法
if(isCycle) return; //剪枝
}
visited[i] = 2; //标记当前结点完成遍历,意义不太明白,考虑的是当有多个子图的情况
}