Course Schedule
There are a total of n courses you have to take, labeled from 0 to n - 1.
Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]
Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses?
For example:
2, [[1,0]]
There are a total of 2 courses to take. To take course 1 you should have finished course 0. So it is possible.
2, [[1,0],[0,1]]
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.
Analysis
基本思路:
- 循环所有的sink vertex (没有outgoing的edge)放入queue,记录标记count(count初始化为vertex数量)
 - 去掉这个sink vertex和与之相连的edge,找到下一个sink vertex,放入queue,记录标记为--count
 - 最后看看是不是所有的vertex都能标记(count==0)
 
Code
public boolean canFinish(int numCourses, int[][] prerequisites) {
    //用来标记所有的edges
    //用来标记从每个点出去edges的个数
    int[][] matrix = new int[numCourses][numCourses]; // i -> j
    int[] indegree = new int[numCourses];
    for (int i=0; i<prerequisites.length; i++) {
        int ready = prerequisites[i][0];
        int pre = prerequisites[i][1];
        if (matrix[pre][ready] == 0)
            indegree[ready]++; //duplicate case
        matrix[pre][ready] = 1;
    }
    int count = numCourses;
    Queue<Integer> queue = new LinkedList();
    //把所有没有outgoing edge的vertex (sink vertex)都放到queue里面去
    for (int i=0; i<indegree.length; i++) {
        if (indegree[i] == 0) queue.offer(i);
    }
    //情况一:如果queue是空的,说明没有vertex是sink vertex,那么肯定有cycle,不会进入while,return false
    while (!queue.isEmpty()) {
        int course = queue.poll();
        //每找个一个sink vertex,count++,意思是已经可以标记它了
        count--;
        for (int i=0; i<numCourses; i++) {
            //便利所有vertex,如果找到了一个和这个sink vertex course项链的vertex
            if (matrix[course][i] != 0) {
                //--indegree[i]==0,说明和它相连的那个点除去现在这个edge已经没有别的edge,说明它是下一个sink vertex
                if (--indegree[i] == 0)
                    queue.offer(i);
            }
        }
    }
    //count==numCourses说明可以标记所有点,那么一定是acyclic,如果不能标记,就一定有cycle
    return count == 0;
}