207. Course Schedule【力扣】

题意理解

有n个课程,两两课程之间有前置关系,上这个课必须要先上另外一个课。问能不能上完所有课?

问题分析

图论,DFS遍历。

图的结构表示,用vector<vector<int>> graph,邻接表表示。

DFS的算法结构

分两部分

第一部分:设置访问数组vector<int> visited(nums, 0),初值置为0.一个循环遍历所有结点,如果没有访问过,执行DFS;

第二部分:DFS设计,参数是遍历的开始结点,图,访问数组,是否是环,共4个参数,最后一个是遍历的目的。DFS设计的方式是如果被访问过,返回,如果没有,先设置为访问过。然后遍历它的邻接点,每个邻接点递归调用dfs;然后设置当前结点访问结束。

其他

参考https://leetcode.com/problems/course-schedule/discuss/58609/C%2B%2B-clean-code-for-DFS-solution-with-simple-comments

链接

 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;    //标记当前结点完成遍历,意义不太明白,考虑的是当有多个子图的情况
    }    

猜你喜欢

转载自blog.csdn.net/xiexie1357/article/details/88603310