LeetCode207. 课程表

现在你总共有 n 门课需要选,记为 0 到 n-1

在选修某些课程之前需要一些先修课程。 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们: [0,1]

给定课程总量以及它们的先决条件,判断是否可能完成所有课程的学习?

示例 1:

输入: 2, [[1,0]] 
输出: true
解释: 总共有 2 门课程。学习课程 1 之前,你需要完成课程 0。所以这是可能的。

示例 2:

输入: 2, [[1,0],[0,1]]
输出: false
解释: 总共有 2 门课程。学习课程 1 之前,你需要先完成​课程 0;并且学习课程 0 之前,你还应先完成课程 1。这是不可能的。

题目分析:非常好的一道题目,判断一个有向图中是否存在环。借助于BFS,记录下每个点的入度,首先将图中入度为0的点入队,然后在图上删去这个点,并且将与它们相连的点的入度减1,若某个点的入度减为0,则这个点要入队。重复以上步骤,最后图中若所有的点都删除了,则没有环;否则有环。

我们可以借助于map,将这个点指向的所有点,保存在一个vector中,将这个vector作为这个点(key)的value。

代码展示:

class Solution {
public:
    bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
        map<int,vector<int>> mp;
        int inDegree[numCourses];    //表示每个点的入度
        memset(inDegree,0,sizeof(inDegree));
        bool isDeleteNode[numCourses];   //表示该点是否被删除
        memset(isDeleteNode,0,sizeof(isDeleteNode));
        for(auto pre:prerequisites){
            if(mp.find(pre.first)!=mp.end()){
                mp[pre.first].push_back(pre.second);
            }
            else{
                vector<int> vec;
                vec.push_back(pre.second);
                mp[pre.first] = vec;
            }
            inDegree[pre.second] += 1;
        }
        queue<int> q;
        for(int i=0;i<numCourses;i++){  //将所有入度为0的点入队
            if(inDegree[i]==0)
                q.push(i);
        }
        while(!q.empty()){
            int temp = q.front();
            isDeleteNode[temp] = true;   
            q.pop();
            for(auto value:mp[temp]){
                inDegree[value] -= 1;
                if(inDegree[value]==0)
                    q.push(value);
            }
        }
        for(int i=0;i<numCourses;i++){
            if(!isDeleteNode[i])
                return false;
        }
        return true;
    }
};

补充:

本题若是用DFS来做的话,思路是这样的:用一个数组来标记访问过的结点,若在一次深度遍历中,某个结点的下一条边指向了一个已经访问过的结点,则表示有环。

若是判断一个无向图是否有环,步骤是:首先,求出图中所有点的度,将度小于等于1 的点删去,并且将与之相连的点的度减1,重复以上步骤,直到图中的点无法再改动。若还有没有删去的点,则表示有环,否则无环。

猜你喜欢

转载自blog.csdn.net/Jaster_wisdom/article/details/81672848
今日推荐