算法第九周Course Schedule[medium]

来源:互联网 发布:java main启动spring 编辑:程序博客网 时间:2024/06/04 23:27

Course Schedule[medium]


Description

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.

Note:
The input prerequisites is a graph represented by a list of edges, not adjacency matrices. Read more about how a graph is represented.
You may assume that there are no duplicate edges in the input prerequisites.


Solution

这是一道典型的拓扑排序问题。

(摘自维基百科)拓扑排序:在计算机科学领域,有向图的拓扑排序或拓扑排序是其顶点的线性排序,使得对于从顶点 u 到顶点 v 的每个有向边 uv,u 在排序中都在 v 之前。 例如,图形的顶点可以表示要执行的任务,并且边缘可以表示一个任务必须在另一个任务之前执行的约束;在这个应用中,拓扑排序只是一个有效的任务顺序。 如果且仅当图形没有定向循环,即如果它是有向无环图(DAG),则拓扑排序是可能的。 任何 DAG 具有至少一个拓扑排序,并且已知这些算法用于在线性时间内构建任何 DAG 的拓扑排序。在图论中,由一个有向无环图的顶点组成的序列,当且仅当满足下列条件时,称为该图的一个拓扑排序(英语:Topological sorting)。每个顶点出现且只出现一次;若A在序列中排在B的前面,则在图中不存在从B到A的路径。也可以定义为:拓扑排序是对有向无环图的顶点的一种排序,它使得如果存在一条从顶点A到顶点B的路径,那么在排序中B出现在A的后面[1]。

本题的课程就相当于图中的顶点,而一个课程A必须在课程B之前完成就相当于存在一条A到B的边,如果得到图是有向无环图,那么就可以找到一个拓扑排序。
我们可以使用一个数组indegree来记录图中每个顶点(即每个课程)的入度,找到入度为0的顶点作为起点,将它从图中删除,即将它指向的顶点的入度减一,不断寻找删除入度为0的顶点,直至全部顶点的入度为0,我们就可以得到一个拓扑排序,即课程调度,如果图中存在环,那么环的顶点的入度永远不可能为0;可以利用DFS或BFS来实现。

class Solution {public:    bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {        if (numCourses == 0) return true;        vector<vector<int>> graph(numCourses, vector<int>(0));         int indegree[numCourses];        memset(indegree, 0, sizeof(indegree));        for (int i = 0; i < prerequisites.size(); i++) {            graph[prerequisites[i].second].push_back(prerequisites[i].first);            indegree[prerequisites[i].first] += 1;        }        queue<int> que;        for (int j = 0; j < numCourses; j++) {            if (indegree[j] == 0) {                que.push(j);            }        }        int cur;        while(!que.empty()) {            cur = que.front();            que.pop();            for (int j = 0; j < graph[cur].size(); j++) {                indegree[graph[cur][j]]--;                if (indegree[graph[cur][j]] == 0) {                        que.push(graph[cur][j]);                }            }        }        for (int i = 0; i < numCourses; i++) {            if (indegree[i] != 0) return false;        }        return true;    }};