diff --git a/solution/2800-2899/2876.Count Visited Nodes in a Directed Graph/README.md b/solution/2800-2899/2876.Count Visited Nodes in a Directed Graph/README.md index 598d13d75c492..d9f84c762bfcc 100644 --- a/solution/2800-2899/2876.Count Visited Nodes in a Directed Graph/README.md +++ b/solution/2800-2899/2876.Count Visited Nodes in a Directed Graph/README.md @@ -55,6 +55,17 @@ +**方法一:基环树 + 遍历搜索** + +我们可以用一个数组 $ans$ 记录每个节点的答案,用一个数组 $vis$ 记录每个节点的访问次序。 + +遍历每个节点 $i$,如果当前节点 $i$ 未被访问,我们就从节点 $i$ 开始遍历,此时有两种情况: + +1. 如果遍历过程中,遇到了当前节点出发时走过的节点,那么此次遍历,一定是先走到了环内,然后沿着环走了一圈。对于环外的节点,其答案就是环的长度加上节点到环的距离;对于环内的节点,其答案就是环的长度。 +1. 如果遍历过程中,遇到了此前节点出发时走过的节点,那么对于每个走过的节点,其答案就是当前节点到此节点的距离,加上此节点的答案。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是数组 $edges$ 的长度。 + ### **Python3** @@ -62,13 +73,63 @@ ```python - +class Solution: + def countVisitedNodes(self, edges: List[int]) -> List[int]: + n = len(edges) + ans = [0] * n + vis = [0] * n + for i in range(n): + if not ans[i]: + cnt, j = 0, i + while not vis[j]: + cnt += 1 + vis[j] = cnt + j = edges[j] + cycle, total = 0, cnt + ans[j] + if not ans[j]: + cycle = cnt - vis[j] + 1 + total = cnt + j = i + while not ans[j]: + ans[j] = max(total, cycle) + total -= 1 + j = edges[j] + return ans ``` ### **Java** +```java +class Solution { + public int[] countVisitedNodes(List edges) { + int n = edges.size(); + int[] ans = new int[n]; + int[] vis = new int[n]; + for (int i = 0; i < n; ++i) { + if (ans[i] == 0) { + int cnt = 0, j = i; + while (vis[j] == 0) { + vis[j] = ++cnt; + j = edges.get(j); + } + int cycle = 0, total = cnt + ans[j]; + if (ans[j] == 0) { + cycle = cnt - vis[j] + 1; + } + j = i; + while (ans[j] == 0) { + ans[j] = Math.max(total--, cycle); + j = edges.get(j); + } + } + } + return ans; + } +} +``` + ```java class Solution { void dfs(int curr, List edges, int[] ans) { @@ -106,19 +167,104 @@ class Solution { return ans; } } - ``` ### **C++** ```cpp - +class Solution { +public: + vector countVisitedNodes(vector& edges) { + int n = edges.size(); + vector ans(n), vis(n); + for (int i = 0; i < n; ++i) { + if (!ans[i]) { + int cnt = 0, j = i; + while (vis[j] == 0) { + vis[j] = ++cnt; + j = edges[j]; + } + int cycle = 0, total = cnt + ans[j]; + if (ans[j] == 0) { + cycle = cnt - vis[j] + 1; + } + j = i; + while (ans[j] == 0) { + ans[j] = max(total--, cycle); + j = edges[j]; + } + } + } + return ans; + } +}; ``` ### **Go** ```go +func countVisitedNodes(edges []int) []int { + n := len(edges) + ans := make([]int, n) + vis := make([]int, n) + for i := range ans { + if ans[i] == 0 { + cnt, j := 0, i + for vis[j] == 0 { + cnt++ + vis[j] = cnt + j = edges[j] + } + cycle, total := 0, cnt+ans[j] + if ans[j] == 0 { + cycle = cnt - vis[j] + 1 + } + j = i + for ans[j] == 0 { + ans[j] = max(total, cycle) + total-- + j = edges[j] + } + } + } + return ans +} +func max(a, b int) int { + if a > b { + return a + } + return b +} +``` + +### **TypeScript** + +```ts +function countVisitedNodes(edges: number[]): number[] { + const n = edges.length; + const ans: number[] = Array(n).fill(0); + const vis: number[] = Array(n).fill(0); + for (let i = 0; i < n; ++i) { + if (ans[i] === 0) { + let [cnt, j] = [0, i]; + while (vis[j] === 0) { + vis[j] = ++cnt; + j = edges[j]; + } + let [cycle, total] = [0, cnt + ans[j]]; + if (ans[j] === 0) { + cycle = cnt - vis[j] + 1; + } + j = i; + while (ans[j] === 0) { + ans[j] = Math.max(total--, cycle); + j = edges[j]; + } + } + } + return ans; +} ``` ### **...** diff --git a/solution/2800-2899/2876.Count Visited Nodes in a Directed Graph/README_EN.md b/solution/2800-2899/2876.Count Visited Nodes in a Directed Graph/README_EN.md index 6cc52c113e1b2..f75eb5aad18c2 100644 --- a/solution/2800-2899/2876.Count Visited Nodes in a Directed Graph/README_EN.md +++ b/solution/2800-2899/2876.Count Visited Nodes in a Directed Graph/README_EN.md @@ -49,16 +49,77 @@ ## Solutions +**Solution 1: Basic Tree + Traversal** + +We can use an array $ans$ to record the answer for each node, and an array $vis$ to record the visit order for each node. + +For each node $i$, if it has not been visited yet, we start traversing from node $i$. There are two cases: + +- If we encounter a node that has been visited before during the traversal, then we must have first entered the cycle and then walked around the cycle. For nodes outside the cycle, their answer is the length of the cycle plus the distance from the node to the cycle; for nodes inside the cycle, their answer is the length of the cycle. +- If we encounter a node that has been visited before during the traversal, then for each visited node, its answer is the distance from the current node to this node plus the answer of this node. + +The time complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the length of the array edges. + ### **Python3** ```python - +class Solution: + def countVisitedNodes(self, edges: List[int]) -> List[int]: + n = len(edges) + ans = [0] * n + vis = [0] * n + for i in range(n): + if not ans[i]: + cnt, j = 0, i + while not vis[j]: + cnt += 1 + vis[j] = cnt + j = edges[j] + cycle, total = 0, cnt + ans[j] + if not ans[j]: + cycle = cnt - vis[j] + 1 + total = cnt + j = i + while not ans[j]: + ans[j] = max(total, cycle) + total -= 1 + j = edges[j] + return ans ``` ### **Java** +```java +class Solution { + public int[] countVisitedNodes(List edges) { + int n = edges.size(); + int[] ans = new int[n]; + int[] vis = new int[n]; + for (int i = 0; i < n; ++i) { + if (ans[i] == 0) { + int cnt = 0, j = i; + while (vis[j] == 0) { + vis[j] = ++cnt; + j = edges.get(j); + } + int cycle = 0, total = cnt + ans[j]; + if (ans[j] == 0) { + cycle = cnt - vis[j] + 1; + } + j = i; + while (ans[j] == 0) { + ans[j] = Math.max(total--, cycle); + j = edges.get(j); + } + } + } + return ans; + } +} +``` + ```java class Solution { void dfs(int curr, List edges, int[] ans) { @@ -96,19 +157,104 @@ class Solution { return ans; } } - ``` ### **C++** ```cpp - +class Solution { +public: + vector countVisitedNodes(vector& edges) { + int n = edges.size(); + vector ans(n), vis(n); + for (int i = 0; i < n; ++i) { + if (!ans[i]) { + int cnt = 0, j = i; + while (vis[j] == 0) { + vis[j] = ++cnt; + j = edges[j]; + } + int cycle = 0, total = cnt + ans[j]; + if (ans[j] == 0) { + cycle = cnt - vis[j] + 1; + } + j = i; + while (ans[j] == 0) { + ans[j] = max(total--, cycle); + j = edges[j]; + } + } + } + return ans; + } +}; ``` ### **Go** ```go +func countVisitedNodes(edges []int) []int { + n := len(edges) + ans := make([]int, n) + vis := make([]int, n) + for i := range ans { + if ans[i] == 0 { + cnt, j := 0, i + for vis[j] == 0 { + cnt++ + vis[j] = cnt + j = edges[j] + } + cycle, total := 0, cnt+ans[j] + if ans[j] == 0 { + cycle = cnt - vis[j] + 1 + } + j = i + for ans[j] == 0 { + ans[j] = max(total, cycle) + total-- + j = edges[j] + } + } + } + return ans +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} +``` + +### **TypeScript** +```ts +function countVisitedNodes(edges: number[]): number[] { + const n = edges.length; + const ans: number[] = Array(n).fill(0); + const vis: number[] = Array(n).fill(0); + for (let i = 0; i < n; ++i) { + if (ans[i] === 0) { + let [cnt, j] = [0, i]; + while (vis[j] === 0) { + vis[j] = ++cnt; + j = edges[j]; + } + let [cycle, total] = [0, cnt + ans[j]]; + if (ans[j] === 0) { + cycle = cnt - vis[j] + 1; + } + j = i; + while (ans[j] === 0) { + ans[j] = Math.max(total--, cycle); + j = edges[j]; + } + } + } + return ans; +} ``` ### **...** diff --git a/solution/2800-2899/2876.Count Visited Nodes in a Directed Graph/Solution.cpp b/solution/2800-2899/2876.Count Visited Nodes in a Directed Graph/Solution.cpp new file mode 100644 index 0000000000000..2ba1c01764aad --- /dev/null +++ b/solution/2800-2899/2876.Count Visited Nodes in a Directed Graph/Solution.cpp @@ -0,0 +1,26 @@ +class Solution { +public: + vector countVisitedNodes(vector& edges) { + int n = edges.size(); + vector ans(n), vis(n); + for (int i = 0; i < n; ++i) { + if (!ans[i]) { + int cnt = 0, j = i; + while (vis[j] == 0) { + vis[j] = ++cnt; + j = edges[j]; + } + int cycle = 0, total = cnt + ans[j]; + if (ans[j] == 0) { + cycle = cnt - vis[j] + 1; + } + j = i; + while (ans[j] == 0) { + ans[j] = max(total--, cycle); + j = edges[j]; + } + } + } + return ans; + } +}; \ No newline at end of file diff --git a/solution/2800-2899/2876.Count Visited Nodes in a Directed Graph/Solution.go b/solution/2800-2899/2876.Count Visited Nodes in a Directed Graph/Solution.go new file mode 100644 index 0000000000000..b66c278219bef --- /dev/null +++ b/solution/2800-2899/2876.Count Visited Nodes in a Directed Graph/Solution.go @@ -0,0 +1,33 @@ +func countVisitedNodes(edges []int) []int { + n := len(edges) + ans := make([]int, n) + vis := make([]int, n) + for i := range ans { + if ans[i] == 0 { + cnt, j := 0, i + for vis[j] == 0 { + cnt++ + vis[j] = cnt + j = edges[j] + } + cycle, total := 0, cnt+ans[j] + if ans[j] == 0 { + cycle = cnt - vis[j] + 1 + } + j = i + for ans[j] == 0 { + ans[j] = max(total, cycle) + total-- + j = edges[j] + } + } + } + return ans +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} \ No newline at end of file diff --git a/solution/2800-2899/2876.Count Visited Nodes in a Directed Graph/Solution.java b/solution/2800-2899/2876.Count Visited Nodes in a Directed Graph/Solution.java index 4bd3ed8bff1d8..f12882eb60fdf 100644 --- a/solution/2800-2899/2876.Count Visited Nodes in a Directed Graph/Solution.java +++ b/solution/2800-2899/2876.Count Visited Nodes in a Directed Graph/Solution.java @@ -1,35 +1,25 @@ class Solution { - void dfs(int curr, List edges, int[] ans) { - - List path = new ArrayList<>(); - int prev = -1; - while (ans[curr] == 0) { - path.add(curr); - ans[curr] = prev == -1 ? -1 : ans[prev] - 1; - prev = curr; - curr = edges.get(curr); - } - int idx = path.size() - 1; - if (ans[curr] < 0) { - int cycle = ans[curr] - ans[path.get(idx)] + 1; - int start = ans[curr]; - for (; idx >= 0 && ans[path.get(idx)] <= start; idx--) { - ans[path.get(idx)] = cycle; - } - } - for (; idx >= 0; idx--) { - ans[path.get(idx)] = ans[edges.get(path.get(idx))] + 1; - } - } - public int[] countVisitedNodes(List edges) { int n = edges.size(); int[] ans = new int[n]; - for (int i = 0; i < n; i++) { - if (ans[i] > 0) { - continue; + int[] vis = new int[n]; + for (int i = 0; i < n; ++i) { + if (ans[i] == 0) { + int cnt = 0, j = i; + while (vis[j] == 0) { + vis[j] = ++cnt; + j = edges.get(j); + } + int cycle = 0, total = cnt + ans[j]; + if (ans[j] == 0) { + cycle = cnt - vis[j] + 1; + } + j = i; + while (ans[j] == 0) { + ans[j] = Math.max(total--, cycle); + j = edges.get(j); + } } - dfs(i, edges, ans); } return ans; } diff --git a/solution/2800-2899/2876.Count Visited Nodes in a Directed Graph/Solution.py b/solution/2800-2899/2876.Count Visited Nodes in a Directed Graph/Solution.py new file mode 100644 index 0000000000000..e13381e141c03 --- /dev/null +++ b/solution/2800-2899/2876.Count Visited Nodes in a Directed Graph/Solution.py @@ -0,0 +1,22 @@ +class Solution: + def countVisitedNodes(self, edges: List[int]) -> List[int]: + n = len(edges) + ans = [0] * n + vis = [0] * n + for i in range(n): + if not ans[i]: + cnt, j = 0, i + while not vis[j]: + cnt += 1 + vis[j] = cnt + j = edges[j] + cycle, total = 0, cnt + ans[j] + if not ans[j]: + cycle = cnt - vis[j] + 1 + total = cnt + j = i + while not ans[j]: + ans[j] = max(total, cycle) + total -= 1 + j = edges[j] + return ans diff --git a/solution/2800-2899/2876.Count Visited Nodes in a Directed Graph/Solution.ts b/solution/2800-2899/2876.Count Visited Nodes in a Directed Graph/Solution.ts new file mode 100644 index 0000000000000..f402e09ef6a77 --- /dev/null +++ b/solution/2800-2899/2876.Count Visited Nodes in a Directed Graph/Solution.ts @@ -0,0 +1,24 @@ +function countVisitedNodes(edges: number[]): number[] { + const n = edges.length; + const ans: number[] = Array(n).fill(0); + const vis: number[] = Array(n).fill(0); + for (let i = 0; i < n; ++i) { + if (ans[i] === 0) { + let [cnt, j] = [0, i]; + while (vis[j] === 0) { + vis[j] = ++cnt; + j = edges[j]; + } + let [cycle, total] = [0, cnt + ans[j]]; + if (ans[j] === 0) { + cycle = cnt - vis[j] + 1; + } + j = i; + while (ans[j] === 0) { + ans[j] = Math.max(total--, cycle); + j = edges[j]; + } + } + } + return ans; +}