题意:给出有向图,找出它的拓扑排序
分析与思路:同样还是Course Schedule I(上一个博客)的思路,只不过在每次访问完一个结点的时候把它push起来,为什么呢?因为拓扑排序实际上就是结点按post值从小到大排序的结果,为什么呢?因此拓扑排序后一个结点的进行需要前一个结点的事情完成(遍历完),而post值代表完成的时间,所以,道理很简单(post是什么,还有基本深搜的思路参考上一个博客Course Schedule I的分析与思路,这里只讲额外的思路)
代码:
class Solution {
public:
vector<bool> isVisited;//可以用pre代替的
vector<int> pre;
vector<int> post;
vector<int> result;
int clock;
bool dfs(int nowNode, vector<pair<int, int>>& prerequisites) {
isVisited[nowNode] = true;
pre[nowNode] = clock++;
for (int i = 0; i < prerequisites.size(); i++) {
if (prerequisites[i].first == nowNode) {
if (isVisited[prerequisites[i].second] == true && post[prerequisites[i].second] == -1) return false;//有回边
else if (isVisited[prerequisites[i].second] == false) {
if (!dfs(prerequisites[i].second, prerequisites)) return false;
}
}
}
post[nowNode] = clock++;
result.push_back(nowNode);
return true;
}
vector<int> findOrder(int numCourses, vector<pair<int, int>>& prerequisites) {
result = vector<int>();
isVisited = vector<bool>(numCourses, false);//标记是否访问过
pre = vector<int>(numCourses, -1);
post = vector<int>(numCourses, -1);
clock = 0;
vector<int> toVisited;//源集合
bool flag = true;
vector<bool> hasIn(numCourses, false);//判断找出源
for (int i = 0; i < prerequisites.size(); i++) {
hasIn[prerequisites[i].second] = true;
}
for (int i = 0; i < hasIn.size(); i++) {
if (hasIn[i] == false) toVisited.push_back(i);
}
if (toVisited.empty()) flag = false;//没有源
if (flag != false) {
for (int i = 0; i < toVisited.size(); i++) {
if (!dfs(toVisited[i], prerequisites)) {
flag = false;
break;
}
}
}
for (int i = 0; i < numCourses; i++) {//是否有把所有点遍历过
if (!isVisited[i]) {
flag = false;
break;
}
}
if (flag == false) return vector<int>();
else return result;
}
};