要求:拓扑排序问题,判断环
思路:
法一:dfs,不能以一个节点为开始判断是否会回到该节点,如1指向2,2,3,4之间循环,这样只能暴力太慢。改进一下其实很简单,visited三种状态,0表示未访问,1表示正在访问,2表示已完成访问,遍历到i节点的节点j时,直接dfs j,如果存在环的话j在过程中会碰到处在1状态的i,这时候ans为false
class Solution {
public:
bool ans=true;
void dfs(vector<vector<int>>& edges,vector<int>& visited,int i,int start){
if(!ans)return;
visited[i]=1;
for(int j=0;j<edges[i].size();++j){
if(edges[i][j]==0)continue;
if(visited[j]==0){
dfs(edges,visited,j,start);
if(!ans)return;
}
else if(visited[j]==1){//访问中遇到访问中为环
ans=false;
return;
}
}
visited[i]=2;
}
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
vector<vector<int>> edges(numCourses,vector<int>(numCourses));
vector<int> visited(numCourses);
for(int i=0;i<prerequisites.size();++i)
edges[prerequisites[i][1]][prerequisites[i][0]]=1;
for(int i=0;i<numCourses;++i){
if(!visited[i])
dfs(edges,visited,i,i);
}
return ans;
}
};
法二:正统入度解法
class Solution {
public:
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
vector<vector<int>> edges(numCourses,vector<int>());
vector<int> visited(numCourses);
vector<int> in(numCourses);
for(int i=0;i<prerequisites.size();++i){
edges[prerequisites[i][1]].push_back(prerequisites[i][0]);
in[prerequisites[i][0]]++;
}
queue<int> q;
for(int i=0;i<numCourses;++i){
if(!in[i])
q.push(i);
}
int removecnt=0;
while(!q.empty()){
removecnt++;
int i=q.front();
q.pop();
for(int j:edges[i]){
in[j]--;
if(in[j]==0)q.push(j);
}
}
return removecnt==numCourses;
}
};