1. 程式人生 > 實用技巧 >leetcode207 課程表(Medium)

leetcode207 課程表(Medium)

題目來源:leetcode207 課程表

題目描述:

你這個學期必須選修 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

解題思路:

class Solution {
public:
    bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
       vector<vector<int>> graph(numCourses,vector<int>());//鄰接表,記錄一個結點的後繼
       vector<int> in(numCourses,0);//入度
       for(int i=0;i<prerequisites.size();i++){
           graph[prerequisites[i][1]].push_back(prerequisites[i][0]);
           ++in[prerequisites[i][0]];
       }
       queue<int> q;
       int i=0,num=0;
       //入度為0的結點入隊
       for(i=0;i<numCourses;i++){
           if(in[i]==0){
               q.push(i);
               num++;
           } 
       }
       while(!q.empty()){
           int t=q.front();
           q.pop();
           //入度為0的所有後繼結點的入度-1
           for(i=0;i<graph[t].size();i++){
               in[graph[t][i]]--;
               //如果新得到入度為0的,也加入佇列
               if(in[graph[t][i]]==0){
                   q.push(graph[t][i]);
                   num++;//記錄入度為0的個數
               } 
           }
       }
       //最後所有的結點的入度都為0,如果個數不滿足,則返回false,否則返回true
       if(num==numCourses) return true;
       else  return false;
    }
};