Problem#
給你一個正整數 n 代表課程數量(從 0`` 到
n-1),並給你一個
prerequisites[i] = [a_i, b_i] (int[m][2])的陣列,代表如果要上課程
b_i,一定要先上課程
a_i`
問你能不能上完所有課程?
測資限制#
- 1≤n≤2000
- 0≤m≤5000
- (ai,bi) 不重複
想法#
觀察一下可以發現(第二個 example),如果課程存在循環依賴,則無法完成所以有課程,反之,不存在環則一定可以完成
=> 把 prerequisites
轉成 graph,接著用找環的演算法即可。
DFS 塗顏色,一開始全部都白色(0
),接著開始 dfs,遇到白色的點就塗上紅色(1
),如果在 dfs 的過程遇到紅色(1
)的點,代表存在環。
為了要枚舉 n
個點當起點去 dfs ,所以如果點 i
的邊都 dfs 完了,則把點 i
塗成藍色(2
),之後找沒有塗過的點(白色0
)去 dfs
- 時間複雜度: O(n+m)
- 空間複雜度: O(n)
AC Code#
Copy
// dfs coloring class Solution { public: bool canFinish(int n, vector<vector<int>>& preq) { int m = preq.size(); vector<char> color(n); // 0, 1, 2 vector<vector<int>> req(n, vector<int>{}); function<bool(int)> dfs = [&](int x) -> bool { color[x] = 1; for(int y : req[x]) { if(color[y] == 0) { color[y] = 1; if(dfs(y)) return 1; } else if(color[y] == 1) return 1; } color[x] = 2; return 0; }; for(int i = 0; i < m; i++) { int a = preq[i][0], b = preq[i][1]; req[a].push_back(b); } for(int i = 0; i < n; i++) if(color[i] == 0 && dfs(i)) return 0; return 1; }