LeetCode 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.
此题用基本的图论搜索方法可以解决(BFS或者DFS),判断是否存在环。
解法一:BFS(拓扑排序)
bool canFinish(int numCourses, vector<pair<int, int> >& prerequisites)
{
vector<set<int> > matrix(numCourses);//用矩阵(二维数组)的方式保存图
for (int i = 0; i < prerequisites.size(); i++)
matrix[prerequisites[i].second].insert(prerequisites[i].first);
vector<int> degree(numCourses, 0);
for (int i = 0; i < numCourses; i++)
{
for (set<int>::iterator it = matrix[i].begin(); it != matrix[i].end(); ++it)
{
++degree[*it];//入度增一
}
}
for (int i = 0; i < numCourses; i++)
{
int j;
for (j = 0; j < numCourses && degree[j] != 0; j++){}//找出入度为0的顶点
if (j == numCourses) //没有入度为0的点,则不能完成
return false;
degree[j] = -1;
//将所有以该顶点为起始顶点的入度减一
for (set<int>::iterator it = matrix[j].begin(); it != matrix[j].end(); ++it)
{
--degree[*it];
}
}
return true;
}
解法二:DFS(深搜判断是否存在环)
bool DFS(vector<set<int> >& matrix, set<int>& visited, int v, vector<bool>& flag)
{
flag[v] = true;//访问标记设为true
visited.insert(v);//将顶点v插入已访问的顶点集合
for (set<int>::iterator it = matrix[v].begin(); it != matrix[v].end(); ++it)
{
if (visited.find(*it) != visited.end() || DFS(matrix, visited, *it, flag))//如果已经访问过,则存在环
{
return true;
}
}
visited.erase(v);//回溯
return false;
}
bool canFinish(int numCourses, vector<pair<int, int> >& prerequisites)
{
vector<set<int> > matrix(numCourses);//用矩阵(二维数组)的方式保存图
for (int i = 0; i < prerequisites.size(); i++)
matrix[prerequisites[i].second].insert(prerequisites[i].first);
set<int> visited;//已访问的顶点组成的集合
vector<bool> flag(numCourses, false);//顶点的访问标记,false表示未访问
for (int i = 0; i < numCourses; i++)
{
if (!flag[i])//该顶点为访问,则以该顶点为起始点进行深搜
{
if (DFS(matrix, visited, i, flag))//如果遍历到相同的顶点,则存在环,返回false
return false;
}
}
return true;
}