问题描述:
题目描述了课程学习的优先级,如果出现不可能的学习情况,则表示该schedule是不可能的。
问题分析:
该问题可以转换成有向无环图的问题,若该图中存在了有向无环图,例如 存在a->b,和b->a的边,很显然,这是不可能成为schedule的,因为如果先修a再修b,那么就不能存在先修b再修a,根据《算法概论》3.3.2这一节中,如果存在回边,那么这个有向图就是有环的,那么思路很明显了,可以先进行DFS,记录下各个顶点的post值,如果存在回边(u,v)。即post(u)<post(v)的情况,那么证明存在回边。
但是如下的方法,在Leetcode测试样本中,有个2000的节点,测试显示内存超出,由于邻接矩阵占用的内存较大,所以希望通过邻接表的形式降低内存的消耗,希望能A掉,该方法会在下一次的博客中进行展示,to be continued,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
程序如下:
class Solution {
public:
bool *visited;
int **edges;
int *pre;
int *post;
int index=0;
bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
int *vertex=new int[numCourses];
post=new int[numCourses];
pre=new int[numCourses];
for (int i=0;i<numCourses;i++){
vertex[i]=i;
post[i]=0;
pre[i]=0;
}
edges=new int*[numCourses];
for(int i=0;i<numCourses;i++){
edges[i]=new int[numCourses];
}
for(int i=0;i<numCourses;i++){
for(int j=0;j<numCourses;j++){
edges[i][j]=0;
}
}
for(int i=0;i<prerequisites.size();i++){
int a0=prerequisites[i].first;
int a1=prerequisites[i].second;
edges[a0][a1]=1;
}
DFSTraverse(numCourses);
bool isSchedual=test(prerequisites);
return isSchedual;
}
void DFSTraverse(int numCourses){
visited=new bool[numCourses];
for (int i=0;i<numCourses;i++){
visited[i]=false;
}
for (int i=0;i<numCourses;i++){
if(!visited[i]){
DFSFunction(numCourses,i);
}
}
}
void DFSFunction(int numCourses,int i){
visited[i]=true;
pre[i]=index++;
for(int j=0;j<numCourses;j++){
if(edges[i][j]!=0&&!visited[j]){
DFSFunction(numCourses,j);
}
}
post[i]=index++;
}
bool test(vector<pair<int, int>>& prerequisites){
for(int i=0;i<prerequisites.size();i++){
int a0=prerequisites[i].first;
int a1=prerequisites[i].second;
if(post[a0]<post[a1]){
return false;
}
}
return true;
}
};