拓扑排序

说实话这个名字真的很高大上,第一次接触应该是在离散数学里。数据结构在讲图的时候也提过一次。 那么,在生活中有什么运用呢?比较典型的就是课程表,譬如大学物理的先修课程是高等数学,那么大学物理就必须要在高等数学之后上,而大学物理如果和马克思主义基本原理没什么关系的话,那你就可以在修完高等数学后同时修大学物理和马克思主义基本原理。当然你也可以同时修高等数学和马克思主义基本原理,然后再修大学物理。但不论如何,大学物理都必须在高等数学之后修。(看出来我在说哪个学校了嘛)

算法简述

1.构造反向图,并同时获得所有反向图节点的入度(即原图出度)。 2.将所有入度为0的点(即原图中出度为0的点,也就是终点)加入队列。 3.用bfs搜索反向图中所有安全点,在这个过程中会遍历以安全点为起点的所有有向边,将该点指向的所有点的入度减一;若某点入度变为0则将此点入队。

常见疑惑的说明:

代码实现

class TopologicalSort {
public:  
    vector<int> topologicalSort(vector<vector<int>> &graph)//the graph is shown as {{},{}},the nth vector means the edge starting from vertex n 
    {
        int n=graph.size();
        vector<vector<int>> rg(n);//reconstruct and reverse the graph
        vector<int> inDeg(n);
        for(int x=0;x<n;x++) 
        {
            for(const int &y:graph[x]) 
                rg[y].push_back(x);
            inDeg[x]=graph[x].size();
        }
        vector<int> ret;
        queue<int> q;
        for(int i=0;i<n;i++) 
        {
            if(inDeg[i]==0) 
            {
                q.push(i);//dst
                ret.emplace_back(i);
            }                
        }

        while(!q.empty())//use bfs to traverse the vertex ending in safe vertex
        {
            int node=q.front();
            q.pop();
            for(const int &vertex:rg[node]) 
            {
                if(--inDeg[vertex]==0)//indeg=0 means safety
                {
                    q.push(vertex);
                    ret.emplace_back(vertex);
                }
            }
        }

        if(ret.size()==n)
          return ret;
        return {};
    }

};
时间复杂度 空间复杂度 补充说明 适用范围
\(O(n+m)\) \(O(n+m)\) n为点数,m为边数 无

例题:
力扣207课程表 https://leetcode-cn.com/problems/course-schedule/