207. 课程表

广度优先遍历+拓扑排序--检测是否存在环

拓扑排序:1. 所有入度为0的顶点加入队列

                  2. 取出队列中的一个顶点,将以该顶点为出度的边删除

                  3. 查看删除这条边后,以这条边为入度的顶点的入度是否为0,如果为0加入队列

                  4. 如果队不为空,循环遍历1-3

如果所有顶点的入度都为0那么说明没有环,如果存在入度不为0的点,那么说明存在环。

该题是典型的拓扑排序题,只需要检测是否存在环即可,如果不存在返回true,如果存在返回false

class Solution {
public:
/*要想学完所有课程:1.不能有回路(第二个值不能遍历过
遍历有向无环图,看图中是否有环,如果没有环怎返回true,否则返回false
拓扑排序:1. 寻找所有入度为0的顶点将其入队
*/
    bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
        map<int,int> mp;
        // 将所有顶点存入map中,入度置为0
        for(int i=0;i<prerequisites.size();i++){
            mp[prerequisites[i][0]] = 0;
            mp[prerequisites[i][1]] = 0;
        }
        // 统计所有顶点的入度
        for(int i=0;i<prerequisites.size();i++){
            mp[prerequisites[i][1]]++;  // 统计入度
        }
        queue<int> q;
        // 将所有入度为0的顶点加入队列
        for(auto m:mp){
            if(m.second == 0){
                q.push(m.first);
            }
        }
        // 广度优先遍历
        // 直到队列为空时,查看mp是否还有入度不为零的顶点,如果有说明存在环,如果没有则不存在环
        while(!q.empty()){
            int p = q.front(); // 选择第一个入列
            q.pop();
            // 将以该顶点入度的顶点入度数减一
            for(int i=0;i<prerequisites.size();i++){
                if(prerequisites[i][0] == p) {
                    mp[prerequisites[i][1]]--;
                    if(mp[prerequisites[i][1]] == 0){
                        // 该顶点为0了,将其入列
                        q.push(prerequisites[i][1]);
                    }
                }
            }
        }
        for(auto m:mp){
            // cout<<m.first<<" "<<m.second<<endl;
            if(m.second!=0){
                return false;
            }
        }
        return true;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值