class Solution {
public:
vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
vector<int> tp; // 存储拓扑排序结果
vector<vector<int>> e(numCourses); // 邻接表存储依赖关系
vector<int> din(numCourses, 0); // 每个节点的入度
// 构建图
for (auto &q : prerequisites) {
int a = q[0], b = q[1];
// b -> a
e[b].push_back(a);
din[a]++;
}
// 最小堆实现拓扑排序
priority_queue<int, vector<int>, greater<int>> minHeap;
// 将所有入度为 0 的节点加入最小堆
for (int i = 0; i < numCourses; i++) {
if (din[i] == 0) {
minHeap.push(i);
}
}
// 拓扑排序
while (!minHeap.empty()) {
int x = minHeap.top(); // 取堆中最小的节点
minHeap.pop();
tp.push_back(x); // 将节点加入拓扑结果
// 遍历当前节点的所有出边
for (auto &p : e[x]) {
if (--din[p] == 0) { // 如果节点的入度变为 0
minHeap.push(p); // 将节点加入最小堆
}
}
}
// 如果拓扑排序的结果数量不等于节点总数,则说明存在环
if (tp.size() != numCourses) return {};
return tp;
}
};
class Solution {
public:
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
vector<vector<int>> g(numCourses);
for (auto& p : prerequisites) {
g[p[0]].push_back(p[1]);
}
vector<int> colors(numCourses);
auto dfs = [&](this auto&& dfs, int x) -> bool {
colors[x] = 1; // x 正在访问中
for (int y : g[x]) {
if (colors[y] == 1 || colors[y] == 0 && dfs(y)) {
return true; // 找到了环
}
}
colors[x] = 2; // x 完全访问完毕
return false; // 没有找到环
};
for (int i = 0; i < numCourses; i++) {
if (colors[i] == 0 && dfs(i)) {
return false; // 有环
}
}
return true; // 没有环
}
};