课程表 IV
你总共需要上 numCourses
门课,课程编号依次为 0
到 numCourses-1
。你会得到一个数组 prerequisite
,其中 prerequisites[i] = [ai, bi]
表示如果你想选 bi
课程,你必须先选 ai
课程。
先决条件也可以是 间接 的。如果课程 a 是课程 b 的先决条件,课程 b 是课程 c 的先决条件,那么课程 a 就是课程 c 的先决条件。
你也得到一个数组 queries
,其中 queries[j] = [uj, vj]
。对于第 j
个查询,您应该回答课程 uj
是否是课程 vj
的先决条件。
返回一个布尔数组 answer
,其中 answer[j]
是第 j
个查询的答案。
思路及解析
-
首先,我们构建了一个课程依赖关系图
graph
,其中每个节点代表一个课程,每个边表示一个课程的先修课程。我们遍历prerequisites
中的先修课程关系,将这些关系添加到图中。 -
然后,我们创建了一个二维矩阵
dp
,其中 dp[i][j] 表示课程 i 是否是课程 j 的先修课程。最初,所有的dp[i][j]
都被初始化为false
。 -
接下来,我们使用深度优先搜索来填充
dp
矩阵。我们从每个课程出发,尝试找到从当前课程到其他课程的所有可能路径,并在dp
矩阵中标记这些课程之间的依赖关系。 -
最后,对于查询中的每一对课程 (x, y),我们检查
dp[y][x]
是否为true
。如果是true
,则表示课程 x 是课程 y 的先修课程,否则不是。
class Solution {
public:
vector<bool> checkIfPrerequisite(int numCourses, vector<vector<int>>& prerequisites, vector<vector<int>>& queries) {
vector<vector<int>> graph(numCourses, vector<int>());
// 构建课程依赖关系图
for (const auto& pre : prerequisites) {
graph[pre[0]].push_back(pre[1]);
}
// 使用 dp[i][j] 表示 i 是否是 j 的先决条件
vector<vector<bool>> dp(numCourses, vector<bool>(numCourses, false));
for (int i = 0; i < numCourses; ++i) {
dfs(i, i, graph, dp);
}
// 查询每一对课程是否有依赖关系
vector<bool> answer;
for (const auto& q : queries) {
answer.push_back(dp[q[0]][q[1]]);
}
return answer;
}
private:
void dfs(int start, int cur, vector<vector<int>>& graph, vector<vector<bool>>& dp){
for (int next : graph[cur]) {
if (!dp[start][next]) {
dp[start][next] = true;
dfs(start, next, graph, dp);
}
}
}
};