# 207. Course Schedule(课程安排)

## 1 问题描述

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?

Example 1:

Input: 2, [[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: 2, [[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.


Note:

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

## 2 思路

• 使用深度优先遍历：对输入进行分析，原始问题可以转换为有向图问题，当有向图无环时返回True,当有向图有环时返回False
• 使用宽度优先遍历：只将入度为0的点添加至队列。当完成一个顶点的搜索(从队 列取出)，它指向的所有顶点入度都减1，若此时某顶点入度为0则添加至队列，若完 成宽度搜索后，所有的点入度都为0，则图无环，否则有环。

## 3 C++实现

• 图的实现
struct GraphNode{
int label;
std::vector<GraphNode *> neighbors;
GraphNode(int x) : label(x) {};
};

• 方法一：深度优先遍历
class Solution {
public:
bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
vector<GraphNode *> graph;
vector<int> visit;
//创建图
for(int i=0; i<numCourses; i++) {
graph.push_back(new GraphNode(i));
visit.push_back(-1);
}

//连接图
for(int i=0; i<prerequisites.size(); i++) {
GraphNode* begin = graph[prerequisites[i].second];
GraphNode* end = graph[prerequisites[i].first];
begin->neighbors.push_back(end);
}

//遍历
for(int i=0; i<graph.size(); i++) {
if(visit[i] == -1 && !DFS_graph(graph[i], visit))
return false;
}
//回收内存
for(int i=0; i<graph.size(); i++) {
delete graph[i];
}

return true;
}

private:
bool DFS_graph(GraphNode *node, vector<int> &visit) {
//节点访问控制，-1表示没有访问，0表示正在访问，1表示访问完成
visit[node->label] = 0;
for(int i=0; i<node->neighbors.size(); i++) {
if(visit[node->neighbors[i]->label] == -1) {
if(DFS_graph(node->neighbors[i], visit) == 0)
return false;
}
else if(visit[node->neighbors[i]->label] == 0)
return false;
}
visit[node->label] = 1;
return true;
}
};

• 方法二，宽度优先(拓扑结构)
class Solution {
public:
bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
vector<GraphNode *> graph;
vector<int> degree;
//创建图
for(int i=0; i<numCourses; i++) {
graph.push_back(new GraphNode(i));
degree.push_back(0);
}

//连接图
for(int i=0; i<prerequisites.size(); i++) {
GraphNode* begin = graph[prerequisites[i].second];
GraphNode* end = graph[prerequisites[i].first];
begin->neighbors.push_back(end);
degree[prerequisites[i].first]++;
}

queue<GraphNode *> Q;
for(int i=0; i<degree.size(); i++) {
if(degree[i] == 0)
Q.push(graph[i]);
}

while(!Q.empty()) {
GraphNode* node = Q.front();
Q.pop();
for(int i=0; i<node->neighbors.size(); i++) {
degree[node->neighbors[i]->label]--;
if(degree[node->neighbors[i]->label] == 0)
Q.push(node->neighbors[i]);
}
}

//回收内存
for(int i=0; i<graph.size(); i++) {
delete graph[i];
}

//回收内存
for(int i=0; i<degree.size(); i++) {
if (degree[i]){
return false;
}
}
return true;
}
};