[拓撲排序]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;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章