能進行拓補排序的圖必須是有向無環圖,直接用DFS判斷圖裏面是否存在環,即不能存在回邊,用兩個時鐘數組記錄每個節點的進入時鐘pre和返回時鐘post,回邊有這樣的特性,如果一條邊(u,v)是一條回邊,那麼pre(u)>pre(v),post(u)<post(v)。
class Solution {
public:
bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
unordered_map<int, vector<int>> adjTable;
for (int i = 0; i < prerequisites.size(); i++) {
adjTable[prerequisites[i].first].push_back(prerequisites[i].second);
}
const int arraySize = numCourses;
bool visited[arraySize];
int preClock[arraySize];
int postClock[arraySize];
int globalClock = 0;
for (int i = 0; i < arraySize; i++) {
visited[i] = false;
preClock[i] = -1;
postClock[i] = -1;
}
stack<int> DFSStack;
for (int i = 0; i < numCourses; i++) {
if (!visited[i]) {
DFSStack.push(i);
while (!DFSStack.empty()) {
int currentNode = DFSStack.top();
preClock[currentNode] = globalClock;
globalClock++;
visited[currentNode] = true;
int count = 0;
for (int j = 0; j < adjTable[currentNode].size(); j++) {
if (!visited[adjTable[currentNode][j]]) {
DFSStack.push(adjTable[currentNode][j]);
count++;
} else if (preClock[currentNode] > preClock[adjTable[currentNode][j]] && postClock[adjTable[currentNode][j]] == -1) {//判斷回邊的條件
return false;
}
}
if (count == 0) {
DFSStack.pop();
postClock[currentNode] = globalClock;
globalClock++;
}
}
}
}
return true;
}
};
第二題仍然按照這個思路,不過這裏要返回排序結果,按照一種拓補排序的算法,給每個節點記錄preClock和postClock,按照postClock的遞減順序排序的話就是一種合法的拓補排序結果,而且深搜的時候,當且僅當節點被pop出棧的時候纔會計算它的postClock,所以也不需要顯式計算postClock,只需要每次pop節點的時候將這個節點插到結果向量的開頭就可以了。
算法描述:
TOPOLOGICAL-SORT(G)
1 call DFS(G) to compute finishing times post[v] for each vertex v
2 as each vertex is finished, insert it onto the front of a linked list
3 return the linked list of vertices
算法複雜度:O(V+E)
代碼:
class Solution {
public:
vector<int> findOrder(int numCourses, vector<pair<int, int>>& prerequisites) {
unordered_map<int, vector<int>> adjTable;
for (int i = 0; i < prerequisites.size(); i++) {
adjTable[prerequisites[i].second].push_back(prerequisites[i].first);
}
int globalClock = 0;
const int vecSize = numCourses;
vector<int> resultVec;
stack<int> nodeStack;
int preClock[vecSize], postClock[vecSize];
bool visited[vecSize];
for (int i = 0; i < vecSize; i++) {
preClock[i] = -1;
postClock[i] = -1;
visited[i] = false;
}
for (int startNode = 0; startNode < numCourses; startNode++) {
if (visited[startNode]) {
continue;
}
nodeStack.push(startNode);
visited[startNode] = true;
preClock[0] = globalClock;
globalClock++;
while (!nodeStack.empty()) {
int curNode = nodeStack.top();
bool pushFlag = false;
for (int i = 0; i < adjTable[curNode].size(); i++) {
if (!visited[adjTable[curNode][i]]) {
nodeStack.push(adjTable[curNode][i]);
visited[adjTable[curNode][i]] = true;
preClock[adjTable[curNode][i]] = globalClock;
globalClock++;
pushFlag = true;
break;
} else if (preClock[adjTable[curNode][i]] < preClock[curNode] && postClock[adjTable[curNode][i]] == -1) {
return {};
}
}
if (!pushFlag) {
nodeStack.pop();
postClock[curNode] = globalClock;
globalClock++;
resultVec.insert(resultVec.begin(), curNode);
}
}
}
return resultVec;
}
};