207. Course Schedule
Description of Problem
There are a total of numCourses courses you have to take, labeled from 0 to numCourses - 1. You are given an array prerequisites where prerequisites[i] = [ai, bi] indicates that you must take course b_i first if you want to take course a_i.
For example, the pair [0, 1], indicates that to take course 0 you have to first take course 1.
Return true if you can finish all courses. Otherwise, return false.
Example 1:
Input: numCourses = 2, prerequisites = [[1,0]]
Output: true
Explanation: There are a total of 2 courses to take.
To take course 1 you should have finished course 0. So it is possible.
Example 2:
Input: numCourses = 2, prerequisites = [[1,0],[0,1]]
Output: false
Explanation: There are a total of 2 courses to take.
To take course 1 you should have finished course 0, and to take course 0 you should also have finished course 1. So it is impossible.
Constraints:
1 <= numCourses <= 20000 <= prerequisites.length <= 5000prerequisites[i].length == 20 <= a_i, b_i < numCourses- All the pairs prerequisites[i] are unique.
Solution
Tags: Graph Theory
Explanation
The method is the same as 210. Course Schedule II. By topological sorting, we can detect the cycle in the graph.
Code (Rust)
use std::collections::HashMap;
impl Solution {
pub fn can_finish(num_courses: i32, prerequisites: Vec<Vec<i32>>) -> bool {
let num_courses = num_courses as usize;
let mut adj_list : Vec<Vec<usize>> = vec![ vec![] ; num_courses ];
let mut is_gray : Vec<bool> = vec![false; num_courses];
let mut is_black : Vec<bool> = vec![false; num_courses];
for p in prerequisites.into_iter(){
let (c1, c2) = (p[1] as usize, p[0] as usize);
adj_list[c1].push(c2);
}
let mut has_loop = false;
for vertex in (0..num_courses) {
if !is_black[vertex] && !is_gray[vertex] && !has_loop {
has_loop = Self::visit(vertex, &adj_list, &mut is_gray, &mut is_black);
}
}
!has_loop
}
fn visit(
vertex : usize,
adj_list : &Vec<Vec<usize>>,
is_gray : &mut Vec<bool>,
is_black : &mut Vec<bool>
) -> bool {
for &v in adj_list[vertex].iter() {
match (is_black[v], is_gray[v]){
(false, false) => {
is_gray[v] = true;
if Self::visit(v, adj_list, is_gray, is_black) == true {
return true;
}
is_gray[v] = false;
}
(false, true) => return true,
_ => {}
}
}
is_black[vertex] = true;
return false;
}
}