zoukankan      html  css  js  c++  java
  • 课程表

    你这个学期必须选修 numCourse 门课程,记为 0 到 numCourse-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。这是不可能的。
     

    提示:

    输入的先决条件是由 边缘列表 表示的图形,而不是 邻接矩阵 。详情请参见图的表示法。
    你可以假定输入的先决条件中没有重复的边。
    1 <= numCourses <= 10^5

    code1:邻接表+bfs;

      从给定的二维数组构造形如a->b邻接表,并计算以b为后继的结点的入度,遍历所有课程,找出入度为0的课程,加入队列

    1. 遍历队列找出入度为0的点,
    2. 把邻接表中以此点为前驱的所有结点的入度都减一,如果发现入度为0的点,加入队列
    3. 直到队列为空,否则重复1-2
    class Solution {
    public:
        bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
            map<int,set<int>> adjcent;//邻接表
            vector<int> indegree(numCourses);//以i为顶点的入度
            for(const auto& edg:prerequisites)
            {
                adjcent[edg[1]].insert(edg[0]);
                ++indegree[edg[0]];
            }
    
            //入度为0的顶点入队列
            queue<int> indegreeZero;
            for(int i=0;i<numCourses;++i)
            {
                if(!indegree[i])
                    indegreeZero.push(i);
            }
    
            int count=0;
            while(!indegreeZero.empty())
            {
                int v=indegreeZero.front();
                indegreeZero.pop();
                ++count;
                auto adj=adjcent[v];
                for(auto i:adj)
                {
                    --indegree[i];//以i为前驱的结点的入度减一
                    if(!indegree[i])
                        indegreeZero.push(i);
                }
            }
            return count==numCourses;
        }
    };

     code:dfs,每个结点有个访问标记flag;

    1. 如果该结点没有被访问过,flag==0
    2. 如果结点点被其他结点启动的dfs访问过,flag==-1
    3. 如果该结点被当前节点启动的dfs访问过,flag==1

    以每个课程为起点,dfs邻接表,判断每个结点起步的dfs是否存在环,若存在返回false,对该结点的邻接点进行dfs

    1. 如果flag==-1,说明被其他结点访问过无需再次遍历,返回true,如果flag==1,说明在此次dfs中2次来到该结点,则存在环,返回false
    2. 将当前访问结点的flag置为1
    3. 对以该结点起步的所有邻接点进行dfs,如果发现换返回false
    4. 把该节点的flag置为-1
    5. 若整个图遍历结束未存在环,返回true
    class Solution {
    private:
        bool dfs(const vector<list<int>>& adjcent,int i,vector<int>& flag)
        {
            if(flag[i]==1)
                return false;
            if(flag[i]==-1)
                return true;
            
            flag[i]=1;
            for(const auto& item:adjcent[i])
            {
                if(dfs(adjcent,item,flag)==false)
                    return false;
            }
            flag[i]=-1;
            return true;
        }
    public:
        bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
            vector<list<int>> adjcent(numCourses,list<int>());
            vector<int> flag(numCourses,0);
            for(const auto& edg:prerequisites)
                adjcent[edg[1]].push_back(edg[0]);
            for(int i=0;i<numCourses;++i)
            {
                if(dfs(adjcent,i,flag)==false)
                    return false;
            }
            return true;
        }
    };
  • 相关阅读:
    Linux 忘记root密码
    Linux 基础命令
    Linux 运行级别
    Oracle 体系结构
    Oracle 数据库启动过程
    数据库设计范式
    Oracle通过ROWID删除表中重复记录
    JACASCRIPT--的奇技技巧的44招
    css 的小细节,小总结
    关于我们DOM的知识点
  • 原文地址:https://www.cnblogs.com/tianzeng/p/12486756.html
Copyright © 2011-2022 走看看