问题:课程之间具有依赖性,比如必须先修某门课,然后才可以修另外的课程。给你一些课程,以及课程的依赖关系,求是否能够完成所有课程
思路:这种题属于任务队列,先根据依赖关系建立邻接表数组,然后选出所有入度为0的课程入队,修完这些课,相应的依赖课程的入度减1,然后再继续将入度为0的课程入队,直到队列为空。此时判断:如果入队的课程数等于总的课程数,说明每一门课程都入队了,也就是说每门课的入度都降为0,所以可以完成所有课程;如果入队的课程数不等于总的课程数,说明不可以完成所有课程。
class Solution {
public:struct edge{
int from,to,next;
edge(int u=0,int v=0,int n=0):from(u),to(v),next(n){}
}edges[10000];//最多的边数,这里随便设置的最多10000条边,没想到竟然能过
int FIRST[10000];//每个节点的第一条边,这里同样是随便设置的最多10000个节点
int edge_count;//实际边的数量
void add_edge(int from,int to){
edge_count++;
edges[edge_count]=edge(from,to,FIRST[from]);
FIRST[from]=edge_count;
}
bool canFinish(int numCourses, vector<pair<int,int> >& prerequisites) {
if(numCourses<0) return false;
if(numCourses==0) return true;
if(prerequisites.size()==0) return true;
//初始化节点的入度
int* degree=new int[numCourses];
for(int i=0;i<numCourses;i++){
degree[i]=0;
}
//建立图
for(vector<pair<int,int> >::iterator iter=prerequisites.begin();iter!=prerequisites.end();iter++){
int from=iter->second;
int to=iter->first;
add_edge(from,to);
degree[to]++;
}
queue<int> canfinish;
//入度为0的课程入队
for(int i=0;i<numCourses;i++){
if(degree[i]==0){
canfinish.push(i);
}
}
//记录可以完成的课程数量
int canfinish_num=0;
while(!canfinish.empty()){
int front_node=canfinish.front();
//每完成一个课程,相关的依赖课程的入度就减1
for(int iter=FIRST[front_node];iter;iter=edges[iter].next){
int to=edges[iter].to;
degree[to]--;
if(0==degree[to]){
canfinish.push(to);
}
}
canfinish_num++;
canfinish.pop();
}
//只有当入队的数量等于课程总数量,说明课程都可以入队,也就是入度都能降成0,所以true
if(canfinish_num==numCourses) return true;
else return false;
}
};