[拓扑排序]leetcode210:课程表 Ⅱ (medium)

题目:
在这里插入图片描述
题解:

  • 拓扑排序,与207. 课程表代码一样的,只是将拓扑排序的顶点保留而已,注意边的数组给的是反向,这样的话,我们要将res反转就行了。
  • 算法步骤:
  • 1)遍历边的数组prerequisites建立图的邻接表
  • 2)使用队列来存放入度为0的顶点,从而避免重复检测入度为0的顶点
  • 3)删除入度为0的点,以及删除该点为起点的边,并统计删除入度为0的顶点个数
  • 4)若有向图无环,则res.size()等于顶点数numCounses;否则有向图有环,则res.size()会小于顶点数numCounses

拓扑排序算法思路:

  • 1)在有向图中选一个入度为0的顶点且输出之
  • 2)从图中删除该顶点和所有以它为弧尾的弧
  • 3)重复上述两步,直至全部顶点均已输出,或者当前图中不存在无前驱的顶点为止。=后者表示的是该有向图存在环

代码如下:

class Solution {
public:
    vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
        map<int,set<int>> adjacent;//邻接表
        vector<int> indegree(numCourses);//存放顶点入度的数组
        //1、遍历图的边,建立邻接表和存放顶点入度的数组
        for(auto& edge:prerequisites){
            int a=edge[0],b=edge[1];
            adjacent[a].insert(b);
            ++indegree[b];
        }
        //2、使用队列来存放入度为0的顶点,从而避免重复检测入度为0的顶点
        queue<int> todo;
        for(int i=0;i<numCourses;++i){
            if(!indegree[i])todo.push(i);
        }
        //3、删除入度为0的点,以及删除该点为起点的边,并统计删除入度为0的顶点个数
        vector<int> res;
        while(!todo.empty()){
            auto v=todo.front();//入度为0的顶点
            todo.pop();
            res.push_back(v);
            auto & adjs=adjacent[v];//v的所有邻接点,即弧头为v所有弧的弧尾
            //对v号顶点的每个邻接点的入度减1,若入度为0了,则加入队列中
            for(auto adj:adjs){
                --indegree[adj];
                if(!indegree[adj])todo.push(adj);
            }
        }
        //4、若有向图无环,则count等于顶点数numCounses;否则有向图有环,则count会小于顶点数numCounses
        if(res.size()!=numCourses)return {};
        //注意要将res反转因为图的边可以看成反向的,因此我们进行拓扑排序的结果需要反转
        reverse(res.begin(),res.end());
        return res;
    }
};
发布了512 篇原创文章 · 获赞 175 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/qq_43152052/article/details/104346072