From 2c0a4530fda3afb0378f7e2323f5be2469fb91c8 Mon Sep 17 00:00:00 2001 From: yanglbme Date: Thu, 31 Aug 2023 19:14:27 +0800 Subject: [PATCH 1/2] feat: add solutions to lc problem: No.1462 No.1462.Course Schedule IV --- .../1462.Course Schedule IV/README.md | 350 +++++++++++++----- .../1462.Course Schedule IV/README_EN.md | 324 +++++++++++----- .../1462.Course Schedule IV/Solution.cpp | 67 ++-- .../1462.Course Schedule IV/Solution.go | 58 +-- .../1462.Course Schedule IV/Solution.java | 70 ++-- .../1462.Course Schedule IV/Solution.py | 38 +- .../1462.Course Schedule IV/Solution.ts | 34 ++ 7 files changed, 659 insertions(+), 282 deletions(-) create mode 100644 solution/1400-1499/1462.Course Schedule IV/Solution.ts diff --git a/solution/1400-1499/1462.Course Schedule IV/README.md b/solution/1400-1499/1462.Course Schedule IV/README.md index edb69f982bd3e..9e2a907410651 100644 --- a/solution/1400-1499/1462.Course Schedule IV/README.md +++ b/solution/1400-1499/1462.Course Schedule IV/README.md @@ -70,7 +70,33 @@ -DFS 记忆化搜索。 +**方法一:Floyd 算法** + +我们创建一个二维数组 $f$,其中 $f[i][j]$ 表示节点 $i$ 到节点 $j$ 是否可达。 + +接下来,我们遍历先修课程数组 $prerequisites$,对于其中的每一项 $[a, b]$,我们将 $f[a][b]$ 设为 $true$。 + +然后,我们使用 Floyd 算法计算出所有节点对之间的可达性。 + +具体地,我们使用三重循环,首先枚举中间点 $k$,接下来枚举起点 $i$,最后枚举终点 $j$。对于每一次循环,如果节点 $i$ 到节点 $k$ 可达,且节点 $k$ 到节点 $j$ 可达,那么节点 $i$ 到节点 $j$ 也是可达的,我们将 $f[i][j]$ 设为 $true$。 + +在计算完所有节点对之间的可达性之后,对于每一个查询 $[a, b]$,我们直接返回 $f[a][b]$ 即可。 + +时间复杂度 $O(n^3)$,空间复杂度 $O(n^2)$。其中 $n$ 为节点数。 + +**方法二:拓扑排序** + +与方法一类似,我们创建一个二维数组 $f$,其中 $f[i][j]$ 表示节点 $i$ 到节点 $j$ 是否可达。另外,我们创建一个邻接表 $g$,其中 $g[i]$ 表示节点 $i$ 的所有后继节点;创建一个数组 $indeg$,其中 $indeg[i]$ 表示节点 $i$ 的入度。 + +接下来,我们遍历先修课程数组 $prerequisites$,对于其中的每一项 $[a, b]$,我们更新邻接表 $g$ 和入度数组 $indeg$。 + +然后,我们使用拓扑排序计算出所有节点对之间的可达性。 + +定义一个队列 $q$,初始时将所有入度为 $0$ 的节点加入队列中。随后不断进行以下操作:取出队首节点 $i$,然后遍历 $g[i]$ 中的所有节点 $j$,将 $f[i][j]$ 设为 $true$。接下来,我们枚举节点 $h$,如果 $f[h][i]$ 为 $true$,那么我们也将 $f[h][j]$ 设为 $true$。在这之后,我们将 $j$ 的入度减少 $1$。如果此时 $j$ 的入度为 $0$,那么我们就将 $j$ 加入队列中。 + +在计算完所有节点对之间的可达性之后,对于每一个查询 $[a, b]$,我们直接返回 $f[a][b]$ 即可。 + +时间复杂度 $O(n^2)$,空间复杂度 $O(n^2)$。其中 $n$ 为节点数。 @@ -81,21 +107,41 @@ DFS 记忆化搜索。 ```python class Solution: def checkIfPrerequisite( - self, numCourses: int, prerequisites: List[List[int]], queries: List[List[int]] + self, n: int, prerequisites: List[List[int]], queries: List[List[int]] ) -> List[bool]: - @cache - def dfs(a, b): - if b in g[a] or a == b: - return True - for c in g[a]: - if dfs(c, b): - return True - return False - - g = defaultdict(set) + f = [[False] * n for _ in range(n)] for a, b in prerequisites: - g[a].add(b) - return [dfs(a, b) for a, b in queries] + f[a][b] = True + for k in range(n): + for i in range(n): + for j in range(n): + if f[i][k] and f[k][j]: + f[i][j] = True + return [f[a][b] for a, b in queries] +``` + +```python +class Solution: + def checkIfPrerequisite( + self, n: int, prerequisites: List[List[int]], queries: List[List[int]] + ) -> List[bool]: + f = [[False] * n for _ in range(n)] + g = [[] for _ in range(n)] + indeg = [0] * n + for a, b in prerequisites: + g[a].append(b) + indeg[b] += 1 + q = deque(i for i, x in enumerate(indeg) if x == 0) + while q: + i = q.popleft() + for j in g[i]: + f[i][j] = True + for h in range(n): + f[h][j] = f[h][j] or f[h][i] + indeg[j] -= 1 + if indeg[j] == 0: + q.append(j) + return [f[a][b] for a, b in queries] ``` ### **Java** @@ -104,40 +150,61 @@ class Solution: ```java class Solution { - public List checkIfPrerequisite( - int numCourses, int[][] prerequisites, int[][] queries) { - int[][] g = new int[numCourses][numCourses]; - for (int i = 0; i < numCourses; ++i) { - Arrays.fill(g[i], -1); + public List checkIfPrerequisite(int n, int[][] prerequisites, int[][] queries) { + boolean[][] f = new boolean[n][n]; + for (var p : prerequisites) { + f[p[0]][p[1]] = true; } - for (int[] e : prerequisites) { - int a = e[0], b = e[1]; - g[a][b] = 1; + for (int k = 0; k < n; ++k) { + for (int i = 0; i < n; ++i) { + for (int j = 0; j < n; ++j) { + f[i][j] |= f[i][k] && f[k][j]; + } + } } List ans = new ArrayList<>(); - for (int[] e : queries) { - int a = e[0], b = e[1]; - ans.add(dfs(a, b, g)); + for (var q : queries) { + ans.add(f[q[0]][q[1]]); } return ans; } +} +``` - private boolean dfs(int a, int b, int[][] g) { - if (g[a][b] != -1) { - return g[a][b] == 1; +```java +class Solution { + public List checkIfPrerequisite(int n, int[][] prerequisites, int[][] queries) { + boolean[][] f = new boolean[n][n]; + List[] g = new List[n]; + int[] indeg = new int[n]; + Arrays.setAll(g, i -> new ArrayList<>()); + for (var p : prerequisites) { + g[p[0]].add(p[1]); + ++indeg[p[1]]; } - if (a == b) { - g[a][b] = 1; - return true; + Deque q = new ArrayDeque<>(); + for (int i = 0; i < n; ++i) { + if (indeg[i] == 0) { + q.offer(i); + } } - for (int i = 0; i < g[a].length; ++i) { - if (g[a][i] == 1 && dfs(i, b, g)) { - g[a][b] = 1; - return true; + while (!q.isEmpty()) { + int i = q.poll(); + for (int j : g[i]) { + f[i][j] = true; + for (int h = 0; h < n; ++h) { + f[h][j] |= f[h][i]; + } + if (--indeg[j] == 0) { + q.offer(j); + } } } - g[a][b] = 0; - return false; + List ans = new ArrayList<>(); + for (var qry : queries) { + ans.add(f[qry[0]][qry[1]]); + } + return ans; } } ``` @@ -147,34 +214,64 @@ class Solution { ```cpp class Solution { public: - vector checkIfPrerequisite(int numCourses, vector>& prerequisites, vector>& queries) { - vector> g(numCourses, vector(numCourses, -1)); - for (auto& e : prerequisites) { - int a = e[0], b = e[1]; - g[a][b] = 1; + vector checkIfPrerequisite(int n, vector>& prerequisites, vector>& queries) { + bool f[n][n]; + memset(f, false, sizeof(f)); + for (auto& p : prerequisites) { + f[p[0]][p[1]] = true; + } + for (int k = 0; k < n; ++k) { + for (int i = 0; i < n; ++ i) { + for (int j = 0; j < n; ++ j) { + f[i][j] |= (f[i][k] && f[k][j]); + } + } } vector ans; - for (auto& e : queries) { - int a = e[0], b = e[1]; - ans.push_back(dfs(a, b, g)); + for (auto& q : queries) { + ans.push_back(f[q[0]][q[1]]); } return ans; } +}; +``` - bool dfs(int a, int b, vector>& g) { - if (g[a][b] != -1) return g[a][b] == 1; - if (a == b) { - g[a][b] = 1; - return true; +```cpp +class Solution { +public: + vector checkIfPrerequisite(int n, vector>& prerequisites, vector>& queries) { + bool f[n][n]; + memset(f, false, sizeof(f)); + vector g[n]; + vector indeg(n); + for (auto& p : prerequisites) { + g[p[0]].push_back(p[1]); + ++indeg[p[1]]; + } + queue q; + for (int i = 0; i < n; ++i) { + if (indeg[i] == 0) { + q.push(i); + } } - for (int i = 0; i < g[a].size(); ++i) { - if (g[a][i] == 1 && dfs(i, b, g)) { - g[a][b] = 1; - return true; + while (!q.empty()) { + int i = q.front(); + q.pop(); + for (int j : g[i]) { + f[i][j] = true; + for (int h = 0; h < n; ++h) { + f[h][j] |= f[h][i]; + } + if (--indeg[j] == 0) { + q.push(j); + } } } - g[a][b] = 0; - return false; + vector ans; + for (auto& qry : queries) { + ans.push_back(f[qry[0]][qry[1]]); + } + return ans; } }; ``` @@ -182,42 +279,127 @@ public: ### **Go** ```go -func checkIfPrerequisite(numCourses int, prerequisites [][]int, queries [][]int) []bool { - g := make([][]int, numCourses) - for i := range g { - g[i] = make([]int, numCourses) - for j := range g[i] { - g[i][j] = -1 - } +func checkIfPrerequisite(n int, prerequisites [][]int, queries [][]int) (ans []bool) { + f := make([][]bool, n) + for i := range f { + f[i] = make([]bool, n) } - for _, e := range prerequisites { - a, b := e[0], e[1] - g[a][b] = 1 + for _, p := range prerequisites { + f[p[0]][p[1]] = true } - var ans []bool - var dfs func(a, b int) bool - dfs = func(a, b int) bool { - if g[a][b] != -1 { - return g[a][b] == 1 + for k := 0; k < n; k++ { + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + f[i][j] = f[i][j] || (f[i][k] && f[k][j]) + } } - if a == b { - g[a][b] = 1 - return true + } + for _, q := range queries { + ans = append(ans, f[q[0]][q[1]]) + } + return +} +``` + +```go +func checkIfPrerequisite(n int, prerequisites [][]int, queries [][]int) (ans []bool) { + f := make([][]bool, n) + for i := range f { + f[i] = make([]bool, n) + } + g := make([][]int, n) + indeg := make([]int, n) + for _, p := range prerequisites { + a, b := p[0], p[1] + g[a] = append(g[a], b) + indeg[b]++ + } + q := []int{} + for i, x := range indeg { + if x == 0 { + q = append(q, i) } - for i, c := range g[a] { - if c == 1 && dfs(i, b) { - g[a][b] = 1 - return true + } + for len(q) > 0 { + i := q[0] + q = q[1:] + for _, j := range g[i] { + f[i][j] = true + for h := 0; h < n; h++ { + f[h][j] = f[h][j] || f[h][i] + } + indeg[j]-- + if indeg[j] == 0 { + q = append(q, j) } } - g[a][b] = 0 - return false } - for _, e := range queries { - a, b := e[0], e[1] - ans = append(ans, dfs(a, b)) + for _, q := range queries { + ans = append(ans, f[q[0]][q[1]]) } - return ans + return +} +``` + +### **TypeScript** + +```ts +function checkIfPrerequisite( + n: number, + prerequisites: number[][], + queries: number[][], +): boolean[] { + const f: boolean[][] = Array.from({ length: n }, () => + Array(n).fill(false), + ); + for (const [a, b] of prerequisites) { + f[a][b] = true; + } + for (let k = 0; k < n; ++k) { + for (let i = 0; i < n; ++i) { + for (let j = 0; j < n; ++j) { + f[i][j] ||= f[i][k] && f[k][j]; + } + } + } + return queries.map(([a, b]) => f[a][b]); +} +``` + +```ts +function checkIfPrerequisite( + n: number, + prerequisites: number[][], + queries: number[][], +): boolean[] { + const f: boolean[][] = Array.from({ length: n }, () => + Array(n).fill(false), + ); + const g: number[][] = Array.from({ length: n }, () => []); + const indeg: number[] = Array(n).fill(0); + for (const [a, b] of prerequisites) { + g[a].push(b); + ++indeg[b]; + } + const q: number[] = []; + for (let i = 0; i < n; ++i) { + if (indeg[i] === 0) { + q.push(i); + } + } + while (q.length) { + const i = q.shift()!; + for (const j of g[i]) { + f[i][j] = true; + for (let h = 0; h < n; ++h) { + f[h][j] ||= f[h][i]; + } + if (--indeg[j] === 0) { + q.push(j); + } + } + } + return queries.map(([a, b]) => f[a][b]); } ``` diff --git a/solution/1400-1499/1462.Course Schedule IV/README_EN.md b/solution/1400-1499/1462.Course Schedule IV/README_EN.md index 4320173291b0d..a529416b0fa8b 100644 --- a/solution/1400-1499/1462.Course Schedule IV/README_EN.md +++ b/solution/1400-1499/1462.Course Schedule IV/README_EN.md @@ -61,68 +61,107 @@ Course 0 is not a prerequisite of course 1, but the opposite is true. -DFS. - ### **Python3** ```python class Solution: def checkIfPrerequisite( - self, numCourses: int, prerequisites: List[List[int]], queries: List[List[int]] + self, n: int, prerequisites: List[List[int]], queries: List[List[int]] + ) -> List[bool]: + f = [[False] * n for _ in range(n)] + for a, b in prerequisites: + f[a][b] = True + for k in range(n): + for i in range(n): + for j in range(n): + if f[i][k] and f[k][j]: + f[i][j] = True + return [f[a][b] for a, b in queries] +``` + +```python +class Solution: + def checkIfPrerequisite( + self, n: int, prerequisites: List[List[int]], queries: List[List[int]] ) -> List[bool]: - @cache - def dfs(a, b): - if b in g[a] or a == b: - return True - for c in g[a]: - if dfs(c, b): - return True - return False - - g = defaultdict(set) + f = [[False] * n for _ in range(n)] + g = [[] for _ in range(n)] + indeg = [0] * n for a, b in prerequisites: - g[a].add(b) - return [dfs(a, b) for a, b in queries] + g[a].append(b) + indeg[b] += 1 + q = deque(i for i, x in enumerate(indeg) if x == 0) + while q: + i = q.popleft() + for j in g[i]: + f[i][j] = True + for h in range(n): + f[h][j] = f[h][j] or f[h][i] + indeg[j] -= 1 + if indeg[j] == 0: + q.append(j) + return [f[a][b] for a, b in queries] ``` ### **Java** ```java class Solution { - public List checkIfPrerequisite( - int numCourses, int[][] prerequisites, int[][] queries) { - int[][] g = new int[numCourses][numCourses]; - for (int i = 0; i < numCourses; ++i) { - Arrays.fill(g[i], -1); + public List checkIfPrerequisite(int n, int[][] prerequisites, int[][] queries) { + boolean[][] f = new boolean[n][n]; + for (var p : prerequisites) { + f[p[0]][p[1]] = true; } - for (int[] e : prerequisites) { - int a = e[0], b = e[1]; - g[a][b] = 1; + for (int k = 0; k < n; ++k) { + for (int i = 0; i < n; ++i) { + for (int j = 0; j < n; ++j) { + f[i][j] |= f[i][k] && f[k][j]; + } + } } List ans = new ArrayList<>(); - for (int[] e : queries) { - int a = e[0], b = e[1]; - ans.add(dfs(a, b, g)); + for (var q : queries) { + ans.add(f[q[0]][q[1]]); } return ans; } +} +``` - private boolean dfs(int a, int b, int[][] g) { - if (g[a][b] != -1) { - return g[a][b] == 1; +```java +class Solution { + public List checkIfPrerequisite(int n, int[][] prerequisites, int[][] queries) { + boolean[][] f = new boolean[n][n]; + List[] g = new List[n]; + int[] indeg = new int[n]; + Arrays.setAll(g, i -> new ArrayList<>()); + for (var p : prerequisites) { + g[p[0]].add(p[1]); + ++indeg[p[1]]; } - if (a == b) { - g[a][b] = 1; - return true; + Deque q = new ArrayDeque<>(); + for (int i = 0; i < n; ++i) { + if (indeg[i] == 0) { + q.offer(i); + } } - for (int i = 0; i < g[a].length; ++i) { - if (g[a][i] == 1 && dfs(i, b, g)) { - g[a][b] = 1; - return true; + while (!q.isEmpty()) { + int i = q.poll(); + for (int j : g[i]) { + f[i][j] = true; + for (int h = 0; h < n; ++h) { + f[h][j] |= f[h][i]; + } + if (--indeg[j] == 0) { + q.offer(j); + } } } - g[a][b] = 0; - return false; + List ans = new ArrayList<>(); + for (var qry : queries) { + ans.add(f[qry[0]][qry[1]]); + } + return ans; } } ``` @@ -132,34 +171,64 @@ class Solution { ```cpp class Solution { public: - vector checkIfPrerequisite(int numCourses, vector>& prerequisites, vector>& queries) { - vector> g(numCourses, vector(numCourses, -1)); - for (auto& e : prerequisites) { - int a = e[0], b = e[1]; - g[a][b] = 1; + vector checkIfPrerequisite(int n, vector>& prerequisites, vector>& queries) { + bool f[n][n]; + memset(f, false, sizeof(f)); + for (auto& p : prerequisites) { + f[p[0]][p[1]] = true; + } + for (int k = 0; k < n; ++k) { + for (int i = 0; i < n; ++ i) { + for (int j = 0; j < n; ++ j) { + f[i][j] |= (f[i][k] && f[k][j]); + } + } } vector ans; - for (auto& e : queries) { - int a = e[0], b = e[1]; - ans.push_back(dfs(a, b, g)); + for (auto& q : queries) { + ans.push_back(f[q[0]][q[1]]); } return ans; } +}; +``` - bool dfs(int a, int b, vector>& g) { - if (g[a][b] != -1) return g[a][b] == 1; - if (a == b) { - g[a][b] = 1; - return true; +```cpp +class Solution { +public: + vector checkIfPrerequisite(int n, vector>& prerequisites, vector>& queries) { + bool f[n][n]; + memset(f, false, sizeof(f)); + vector g[n]; + vector indeg(n); + for (auto& p : prerequisites) { + g[p[0]].push_back(p[1]); + ++indeg[p[1]]; + } + queue q; + for (int i = 0; i < n; ++i) { + if (indeg[i] == 0) { + q.push(i); + } } - for (int i = 0; i < g[a].size(); ++i) { - if (g[a][i] == 1 && dfs(i, b, g)) { - g[a][b] = 1; - return true; + while (!q.empty()) { + int i = q.front(); + q.pop(); + for (int j : g[i]) { + f[i][j] = true; + for (int h = 0; h < n; ++h) { + f[h][j] |= f[h][i]; + } + if (--indeg[j] == 0) { + q.push(j); + } } } - g[a][b] = 0; - return false; + vector ans; + for (auto& qry : queries) { + ans.push_back(f[qry[0]][qry[1]]); + } + return ans; } }; ``` @@ -167,42 +236,127 @@ public: ### **Go** ```go -func checkIfPrerequisite(numCourses int, prerequisites [][]int, queries [][]int) []bool { - g := make([][]int, numCourses) - for i := range g { - g[i] = make([]int, numCourses) - for j := range g[i] { - g[i][j] = -1 - } +func checkIfPrerequisite(n int, prerequisites [][]int, queries [][]int) (ans []bool) { + f := make([][]bool, n) + for i := range f { + f[i] = make([]bool, n) } - for _, e := range prerequisites { - a, b := e[0], e[1] - g[a][b] = 1 + for _, p := range prerequisites { + f[p[0]][p[1]] = true } - var ans []bool - var dfs func(a, b int) bool - dfs = func(a, b int) bool { - if g[a][b] != -1 { - return g[a][b] == 1 + for k := 0; k < n; k++ { + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + f[i][j] = f[i][j] || (f[i][k] && f[k][j]) + } } - if a == b { - g[a][b] = 1 - return true + } + for _, q := range queries { + ans = append(ans, f[q[0]][q[1]]) + } + return +} +``` + +```go +func checkIfPrerequisite(n int, prerequisites [][]int, queries [][]int) (ans []bool) { + f := make([][]bool, n) + for i := range f { + f[i] = make([]bool, n) + } + g := make([][]int, n) + indeg := make([]int, n) + for _, p := range prerequisites { + a, b := p[0], p[1] + g[a] = append(g[a], b) + indeg[b]++ + } + q := []int{} + for i, x := range indeg { + if x == 0 { + q = append(q, i) } - for i, c := range g[a] { - if c == 1 && dfs(i, b) { - g[a][b] = 1 - return true + } + for len(q) > 0 { + i := q[0] + q = q[1:] + for _, j := range g[i] { + f[i][j] = true + for h := 0; h < n; h++ { + f[h][j] = f[h][j] || f[h][i] + } + indeg[j]-- + if indeg[j] == 0 { + q = append(q, j) } } - g[a][b] = 0 - return false } - for _, e := range queries { - a, b := e[0], e[1] - ans = append(ans, dfs(a, b)) + for _, q := range queries { + ans = append(ans, f[q[0]][q[1]]) } - return ans + return +} +``` + +### **TypeScript** + +```ts +function checkIfPrerequisite( + n: number, + prerequisites: number[][], + queries: number[][], +): boolean[] { + const f: boolean[][] = Array.from({ length: n }, () => + Array(n).fill(false), + ); + for (const [a, b] of prerequisites) { + f[a][b] = true; + } + for (let k = 0; k < n; ++k) { + for (let i = 0; i < n; ++i) { + for (let j = 0; j < n; ++j) { + f[i][j] ||= f[i][k] && f[k][j]; + } + } + } + return queries.map(([a, b]) => f[a][b]); +} +``` + +```ts +function checkIfPrerequisite( + n: number, + prerequisites: number[][], + queries: number[][], +): boolean[] { + const f: boolean[][] = Array.from({ length: n }, () => + Array(n).fill(false), + ); + const g: number[][] = Array.from({ length: n }, () => []); + const indeg: number[] = Array(n).fill(0); + for (const [a, b] of prerequisites) { + g[a].push(b); + ++indeg[b]; + } + const q: number[] = []; + for (let i = 0; i < n; ++i) { + if (indeg[i] === 0) { + q.push(i); + } + } + while (q.length) { + const i = q.shift()!; + for (const j of g[i]) { + f[i][j] = true; + for (let h = 0; h < n; ++h) { + f[h][j] ||= f[h][i]; + } + if (--indeg[j] === 0) { + q.push(j); + } + } + } + return queries.map(([a, b]) => f[a][b]); } ``` diff --git a/solution/1400-1499/1462.Course Schedule IV/Solution.cpp b/solution/1400-1499/1462.Course Schedule IV/Solution.cpp index b4ab10f40ad5a..bad2f96485c14 100644 --- a/solution/1400-1499/1462.Course Schedule IV/Solution.cpp +++ b/solution/1400-1499/1462.Course Schedule IV/Solution.cpp @@ -1,32 +1,37 @@ -class Solution { -public: - vector checkIfPrerequisite(int numCourses, vector>& prerequisites, vector>& queries) { - vector> g(numCourses, vector(numCourses, -1)); - for (auto& e : prerequisites) { - int a = e[0], b = e[1]; - g[a][b] = 1; - } - vector ans; - for (auto& e : queries) { - int a = e[0], b = e[1]; - ans.push_back(dfs(a, b, g)); - } - return ans; - } - - bool dfs(int a, int b, vector>& g) { - if (g[a][b] != -1) return g[a][b] == 1; - if (a == b) { - g[a][b] = 1; - return true; - } - for (int i = 0; i < g[a].size(); ++i) { - if (g[a][i] == 1 && dfs(i, b, g)) { - g[a][b] = 1; - return true; - } - } - g[a][b] = 0; - return false; - } +class Solution { +public: + vector checkIfPrerequisite(int n, vector>& prerequisites, vector>& queries) { + bool f[n][n]; + memset(f, false, sizeof(f)); + vector g[n]; + vector indeg(n); + for (auto& p : prerequisites) { + g[p[0]].push_back(p[1]); + ++indeg[p[1]]; + } + queue q; + for (int i = 0; i < n; ++i) { + if (indeg[i] == 0) { + q.push(i); + } + } + while (!q.empty()) { + int i = q.front(); + q.pop(); + for (int j : g[i]) { + f[i][j] = true; + for (int h = 0; h < n; ++h) { + f[h][j] |= f[h][i]; + } + if (--indeg[j] == 0) { + q.push(j); + } + } + } + vector ans; + for (auto& qry : queries) { + ans.push_back(f[qry[0]][qry[1]]); + } + return ans; + } }; \ No newline at end of file diff --git a/solution/1400-1499/1462.Course Schedule IV/Solution.go b/solution/1400-1499/1462.Course Schedule IV/Solution.go index 521c74b9cfe4a..53b3f8f7929b9 100644 --- a/solution/1400-1499/1462.Course Schedule IV/Solution.go +++ b/solution/1400-1499/1462.Course Schedule IV/Solution.go @@ -1,37 +1,37 @@ -func checkIfPrerequisite(numCourses int, prerequisites [][]int, queries [][]int) []bool { - g := make([][]int, numCourses) - for i := range g { - g[i] = make([]int, numCourses) - for j := range g[i] { - g[i][j] = -1 - } +func checkIfPrerequisite(n int, prerequisites [][]int, queries [][]int) (ans []bool) { + f := make([][]bool, n) + for i := range f { + f[i] = make([]bool, n) } - for _, e := range prerequisites { - a, b := e[0], e[1] - g[a][b] = 1 + g := make([][]int, n) + indeg := make([]int, n) + for _, p := range prerequisites { + a, b := p[0], p[1] + g[a] = append(g[a], b) + indeg[b]++ } - var ans []bool - var dfs func(a, b int) bool - dfs = func(a, b int) bool { - if g[a][b] != -1 { - return g[a][b] == 1 - } - if a == b { - g[a][b] = 1 - return true + q := []int{} + for i, x := range indeg { + if x == 0 { + q = append(q, i) } - for i, c := range g[a] { - if c == 1 && dfs(i, b) { - g[a][b] = 1 - return true + } + for len(q) > 0 { + i := q[0] + q = q[1:] + for _, j := range g[i] { + f[i][j] = true + for h := 0; h < n; h++ { + f[h][j] = f[h][j] || f[h][i] + } + indeg[j]-- + if indeg[j] == 0 { + q = append(q, j) } } - g[a][b] = 0 - return false } - for _, e := range queries { - a, b := e[0], e[1] - ans = append(ans, dfs(a, b)) + for _, q := range queries { + ans = append(ans, f[q[0]][q[1]]) } - return ans + return } \ No newline at end of file diff --git a/solution/1400-1499/1462.Course Schedule IV/Solution.java b/solution/1400-1499/1462.Course Schedule IV/Solution.java index b9ec4b5a73f75..e22837bc760e5 100644 --- a/solution/1400-1499/1462.Course Schedule IV/Solution.java +++ b/solution/1400-1499/1462.Course Schedule IV/Solution.java @@ -1,37 +1,35 @@ -class Solution { - public List checkIfPrerequisite( - int numCourses, int[][] prerequisites, int[][] queries) { - int[][] g = new int[numCourses][numCourses]; - for (int i = 0; i < numCourses; ++i) { - Arrays.fill(g[i], -1); - } - for (int[] e : prerequisites) { - int a = e[0], b = e[1]; - g[a][b] = 1; - } - List ans = new ArrayList<>(); - for (int[] e : queries) { - int a = e[0], b = e[1]; - ans.add(dfs(a, b, g)); - } - return ans; - } - - private boolean dfs(int a, int b, int[][] g) { - if (g[a][b] != -1) { - return g[a][b] == 1; - } - if (a == b) { - g[a][b] = 1; - return true; - } - for (int i = 0; i < g[a].length; ++i) { - if (g[a][i] == 1 && dfs(i, b, g)) { - g[a][b] = 1; - return true; - } - } - g[a][b] = 0; - return false; - } +class Solution { + public List checkIfPrerequisite(int n, int[][] prerequisites, int[][] queries) { + boolean[][] f = new boolean[n][n]; + List[] g = new List[n]; + int[] indeg = new int[n]; + Arrays.setAll(g, i -> new ArrayList<>()); + for (var p : prerequisites) { + g[p[0]].add(p[1]); + ++indeg[p[1]]; + } + Deque q = new ArrayDeque<>(); + for (int i = 0; i < n; ++i) { + if (indeg[i] == 0) { + q.offer(i); + } + } + while (!q.isEmpty()) { + int i = q.poll(); + for (int j : g[i]) { + f[i][j] = true; + for (int h = 0; h < n; ++h) { + f[h][j] |= f[h][i]; + } + if (--indeg[j] == 0) { + q.offer(j); + } + } + } + List ans = new ArrayList<>(); + for (var qry : queries) { + ans.add(f[qry[0]][qry[1]]); + } + return ans; + } } \ No newline at end of file diff --git a/solution/1400-1499/1462.Course Schedule IV/Solution.py b/solution/1400-1499/1462.Course Schedule IV/Solution.py index a4551a3d0f03a..13949d15d5447 100644 --- a/solution/1400-1499/1462.Course Schedule IV/Solution.py +++ b/solution/1400-1499/1462.Course Schedule IV/Solution.py @@ -1,17 +1,21 @@ -class Solution: - def checkIfPrerequisite( - self, numCourses: int, prerequisites: List[List[int]], queries: List[List[int]] - ) -> List[bool]: - @cache - def dfs(a, b): - if b in g[a] or a == b: - return True - for c in g[a]: - if dfs(c, b): - return True - return False - - g = defaultdict(set) - for a, b in prerequisites: - g[a].add(b) - return [dfs(a, b) for a, b in queries] +class Solution: + def checkIfPrerequisite( + self, n: int, prerequisites: List[List[int]], queries: List[List[int]] + ) -> List[bool]: + f = [[False] * n for _ in range(n)] + g = [[] for _ in range(n)] + indeg = [0] * n + for a, b in prerequisites: + g[a].append(b) + indeg[b] += 1 + q = deque(i for i, x in enumerate(indeg) if x == 0) + while q: + i = q.popleft() + for j in g[i]: + f[i][j] = True + for h in range(n): + f[h][j] = f[h][j] or f[h][i] + indeg[j] -= 1 + if indeg[j] == 0: + q.append(j) + return [f[a][b] for a, b in queries] diff --git a/solution/1400-1499/1462.Course Schedule IV/Solution.ts b/solution/1400-1499/1462.Course Schedule IV/Solution.ts new file mode 100644 index 0000000000000..e8116eaadabc1 --- /dev/null +++ b/solution/1400-1499/1462.Course Schedule IV/Solution.ts @@ -0,0 +1,34 @@ +function checkIfPrerequisite( + n: number, + prerequisites: number[][], + queries: number[][], +): boolean[] { + const f: boolean[][] = Array.from({ length: n }, () => + Array(n).fill(false), + ); + const g: number[][] = Array.from({ length: n }, () => []); + const indeg: number[] = Array(n).fill(0); + for (const [a, b] of prerequisites) { + g[a].push(b); + ++indeg[b]; + } + const q: number[] = []; + for (let i = 0; i < n; ++i) { + if (indeg[i] === 0) { + q.push(i); + } + } + while (q.length) { + const i = q.shift()!; + for (const j of g[i]) { + f[i][j] = true; + for (let h = 0; h < n; ++h) { + f[h][j] ||= f[h][i]; + } + if (--indeg[j] === 0) { + q.push(j); + } + } + } + return queries.map(([a, b]) => f[a][b]); +} From 69b093eb82d5dac2ae1bddbdcd02011e1a4250a3 Mon Sep 17 00:00:00 2001 From: yanglbme Date: Thu, 31 Aug 2023 20:06:17 +0800 Subject: [PATCH 2/2] chore: update code --- solution/1400-1499/1462.Course Schedule IV/README.md | 12 +++--------- .../1400-1499/1462.Course Schedule IV/README_EN.md | 12 +++--------- .../1400-1499/1462.Course Schedule IV/Solution.ts | 4 +--- 3 files changed, 7 insertions(+), 21 deletions(-) diff --git a/solution/1400-1499/1462.Course Schedule IV/README.md b/solution/1400-1499/1462.Course Schedule IV/README.md index 9e2a907410651..ba3a1b4372e72 100644 --- a/solution/1400-1499/1462.Course Schedule IV/README.md +++ b/solution/1400-1499/1462.Course Schedule IV/README.md @@ -349,12 +349,8 @@ function checkIfPrerequisite( prerequisites: number[][], queries: number[][], ): boolean[] { - const f: boolean[][] = Array.from({ length: n }, () => - Array(n).fill(false), - ); - for (const [a, b] of prerequisites) { - f[a][b] = true; - } + const f = Array.from({ length: n }, () => Array(n).fill(false)); + prerequisites.forEach(([a, b]) => (f[a][b] = true)); for (let k = 0; k < n; ++k) { for (let i = 0; i < n; ++i) { for (let j = 0; j < n; ++j) { @@ -372,9 +368,7 @@ function checkIfPrerequisite( prerequisites: number[][], queries: number[][], ): boolean[] { - const f: boolean[][] = Array.from({ length: n }, () => - Array(n).fill(false), - ); + const f = Array.from({ length: n }, () => Array(n).fill(false)); const g: number[][] = Array.from({ length: n }, () => []); const indeg: number[] = Array(n).fill(0); for (const [a, b] of prerequisites) { diff --git a/solution/1400-1499/1462.Course Schedule IV/README_EN.md b/solution/1400-1499/1462.Course Schedule IV/README_EN.md index a529416b0fa8b..936422e2bb7b6 100644 --- a/solution/1400-1499/1462.Course Schedule IV/README_EN.md +++ b/solution/1400-1499/1462.Course Schedule IV/README_EN.md @@ -306,12 +306,8 @@ function checkIfPrerequisite( prerequisites: number[][], queries: number[][], ): boolean[] { - const f: boolean[][] = Array.from({ length: n }, () => - Array(n).fill(false), - ); - for (const [a, b] of prerequisites) { - f[a][b] = true; - } + const f = Array.from({ length: n }, () => Array(n).fill(false)); + prerequisites.forEach(([a, b]) => (f[a][b] = true)); for (let k = 0; k < n; ++k) { for (let i = 0; i < n; ++i) { for (let j = 0; j < n; ++j) { @@ -329,9 +325,7 @@ function checkIfPrerequisite( prerequisites: number[][], queries: number[][], ): boolean[] { - const f: boolean[][] = Array.from({ length: n }, () => - Array(n).fill(false), - ); + const f = Array.from({ length: n }, () => Array(n).fill(false)); const g: number[][] = Array.from({ length: n }, () => []); const indeg: number[] = Array(n).fill(0); for (const [a, b] of prerequisites) { diff --git a/solution/1400-1499/1462.Course Schedule IV/Solution.ts b/solution/1400-1499/1462.Course Schedule IV/Solution.ts index e8116eaadabc1..451d88a94c0ea 100644 --- a/solution/1400-1499/1462.Course Schedule IV/Solution.ts +++ b/solution/1400-1499/1462.Course Schedule IV/Solution.ts @@ -3,9 +3,7 @@ function checkIfPrerequisite( prerequisites: number[][], queries: number[][], ): boolean[] { - const f: boolean[][] = Array.from({ length: n }, () => - Array(n).fill(false), - ); + const f = Array.from({ length: n }, () => Array(n).fill(false)); const g: number[][] = Array.from({ length: n }, () => []); const indeg: number[] = Array(n).fill(0); for (const [a, b] of prerequisites) {