课程表

你这个学期必须选修 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;
    }
};
原文地址:https://www.cnblogs.com/tianzeng/p/12486756.html