diff --git a/solution/3400-3499/3413.Maximum Coins From K Consecutive Bags/README.md b/solution/3400-3499/3413.Maximum Coins From K Consecutive Bags/README.md index 199e5c39db64b..0e6dbc46d923c 100644 --- a/solution/3400-3499/3413.Maximum Coins From K Consecutive Bags/README.md +++ b/solution/3400-3499/3413.Maximum Coins From K Consecutive Bags/README.md @@ -86,7 +86,26 @@ tags: #### Python3 ```python - +class Solution: + def maximumCoins(self, coins: List[List[int]], k: int) -> int: + coins.sort(key=itemgetter(0)) + i, total, ans, n = 0, 0, 0, len(coins) + l0, r0, c0 = coins[0] + print(coins) + for l, r, c in coins: + while i < n and r - coins[i][0] + 1 >= k: + # print(r,coins[i][0],total) + l0, r0, c0 = coins[i] + ans = max(total + max(k + l0 - l, 0) * c, ans) + total -= (r0 - l0 + 1) * c0 + i += 1 + + total += (r - l + 1) * c + # print(total,l,r) + if i < n and coins[i][0] != l0: + start_l = r - k + 1 + ans = max(total + max(r0 - start_l + 1, 0) * c0, ans) + return max(ans, total) ``` #### Java @@ -98,13 +117,161 @@ tags: #### C++ ```cpp - +class Solution { +private: + struct interval { + int start = -1, end = -1, value = 0; + + interval() = default; + interval(int _start, int _end, int _value) : start(_start), end(_end), value(_value) {} + + bool operator < (const interval &other) const { + return start < other.start || (start == other.start && end < other.end); + } + int64_t cost() const { return int64_t(value) * (end - start + 1); } + int64_t cost(int len) const { return int64_t(value) * len; } + }; +public: + long long maximumCoins(vector>& coins, int k) { + int N = int(coins.size()); + vector A(N); + + for (int i = 0; i < N; i++) A[i] = {coins[i][0], coins[i][1], coins[i][2]}; + sort(A.begin(), A.end()); + + int64_t ans = 0LL; + { + int64_t value = 0LL; + int right = 0; + for (int left = 0; left < N; left++) { + while (right < N && A[right].end - A[left].start < k) { + value += A[right].cost(); + ++right; + } + + if (right < N) { + int64_t extra = (A[right].start - A[left].start <= k) ? A[right].cost(k - A[right].start + A[left].start) : 0LL; + ans = max(ans, value + extra); + } + + value -= A[left].cost(); + } + } + + { + int64_t value = 0LL; + int left = 0; + for (int right = 0; right < N; right++) { + value += A[right].cost(); + while (A[right].end - A[left].end >= k) { + value -= A[left].cost(); + left++; + } + + int64_t extra = (A[right].end - A[left].start >= k) ? A[left].cost(A[right].end - A[left].start - k + 1) : 0LL; + ans = max(ans, value - extra); + } + } + + return ans; + } +}; ``` #### Go ```go +func maximumCoins(coins [][]int, k int) int64 { + sort.Slice(coins, func(i, j int) bool { + return coins[i][0] < coins[j][0] + }) + + n := len(coins) + var total int64 = 0 + var ans int64 = 0 + i := 0 + l0, r0, c0 := coins[0][0], coins[0][1], coins[0][2] + + for _, seg := range coins { + l, r, c := seg[0], seg[1], seg[2] + + for i < n && r-coins[i][0]+1 >= k { + l0, r0, c0 = coins[i][0], coins[i][1], coins[i][2] + ans = max64(ans, total+int64(max(k+l0-l, 0))*int64(c)) + total -= int64(r0-l0+1) * int64(c0) + i++ + } + + total += int64(r-l+1) * int64(c) + + if i < n && coins[i][0] != l0 { + startL := r - k + 1 + ans = max64(ans, total+int64(max(r0-startL+1, 0))*int64(c0)) + } + } + if total > ans { + ans = total + } + return ans +} + +func max64(a, b int64) int64 { + if a > b { + return a + } + return b +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} +``` +#### Rust + +```rust +use std::cmp::{min, max}; +fn f(coins: &[(i32, i32, i32)], k: i32) -> i64 { + let mut result = 0; + let mut sum = 0; + let mut r = 0; + + for l in 0..coins.len() { + while r < coins.len() && coins[l].0 + k > coins[r].1 { + sum += (coins[r].1 - coins[r].0 + 1) as i64 * coins[r].2 as i64; + r += 1; + } + result = max(result, sum); + if r == coins.len() { + break; + } + let cnt = coins[l].0 + k - coins[r].0; + result = max(result, sum + max(cnt, 0) as i64 * coins[r].2 as i64); + sum -= (coins[l].1 - coins[l].0 + 1) as i64 * coins[l].2 as i64; + } + + result +} + +impl Solution { + pub fn maximum_coins(mut coins: Vec>, k: i32) -> i64 { + let mut coins: Vec<_> = coins.into_iter() + .map(|xs| (xs[0], xs[1], xs[2])) + .collect(); + coins.sort(); + let a = f(&coins, k); + coins.reverse(); + for i in 0..coins.len() { + (coins[i].0, coins[i].1) = (-coins[i].1, -coins[i].0); + } + let b = f(&coins, k); + + max(a, b) + } +} ``` diff --git a/solution/3400-3499/3413.Maximum Coins From K Consecutive Bags/README_EN.md b/solution/3400-3499/3413.Maximum Coins From K Consecutive Bags/README_EN.md index 9e00904c8fcfa..f464c8d483f77 100644 --- a/solution/3400-3499/3413.Maximum Coins From K Consecutive Bags/README_EN.md +++ b/solution/3400-3499/3413.Maximum Coins From K Consecutive Bags/README_EN.md @@ -83,7 +83,26 @@ tags: #### Python3 ```python - +class Solution: + def maximumCoins(self, coins: List[List[int]], k: int) -> int: + coins.sort(key=itemgetter(0)) + i, total, ans, n = 0, 0, 0, len(coins) + l0, r0, c0 = coins[0] + print(coins) + for l, r, c in coins: + while i < n and r - coins[i][0] + 1 >= k: + # print(r,coins[i][0],total) + l0, r0, c0 = coins[i] + ans = max(total + max(k + l0 - l, 0) * c, ans) + total -= (r0 - l0 + 1) * c0 + i += 1 + + total += (r - l + 1) * c + # print(total,l,r) + if i < n and coins[i][0] != l0: + start_l = r - k + 1 + ans = max(total + max(r0 - start_l + 1, 0) * c0, ans) + return max(ans, total) ``` #### Java @@ -95,13 +114,161 @@ tags: #### C++ ```cpp - +class Solution { +private: + struct interval { + int start = -1, end = -1, value = 0; + + interval() = default; + interval(int _start, int _end, int _value) : start(_start), end(_end), value(_value) {} + + bool operator < (const interval &other) const { + return start < other.start || (start == other.start && end < other.end); + } + int64_t cost() const { return int64_t(value) * (end - start + 1); } + int64_t cost(int len) const { return int64_t(value) * len; } + }; +public: + long long maximumCoins(vector>& coins, int k) { + int N = int(coins.size()); + vector A(N); + + for (int i = 0; i < N; i++) A[i] = {coins[i][0], coins[i][1], coins[i][2]}; + sort(A.begin(), A.end()); + + int64_t ans = 0LL; + { + int64_t value = 0LL; + int right = 0; + for (int left = 0; left < N; left++) { + while (right < N && A[right].end - A[left].start < k) { + value += A[right].cost(); + ++right; + } + + if (right < N) { + int64_t extra = (A[right].start - A[left].start <= k) ? A[right].cost(k - A[right].start + A[left].start) : 0LL; + ans = max(ans, value + extra); + } + + value -= A[left].cost(); + } + } + + { + int64_t value = 0LL; + int left = 0; + for (int right = 0; right < N; right++) { + value += A[right].cost(); + while (A[right].end - A[left].end >= k) { + value -= A[left].cost(); + left++; + } + + int64_t extra = (A[right].end - A[left].start >= k) ? A[left].cost(A[right].end - A[left].start - k + 1) : 0LL; + ans = max(ans, value - extra); + } + } + + return ans; + } +}; ``` #### Go ```go +func maximumCoins(coins [][]int, k int) int64 { + sort.Slice(coins, func(i, j int) bool { + return coins[i][0] < coins[j][0] + }) + + n := len(coins) + var total int64 = 0 + var ans int64 = 0 + i := 0 + l0, r0, c0 := coins[0][0], coins[0][1], coins[0][2] + + for _, seg := range coins { + l, r, c := seg[0], seg[1], seg[2] + + for i < n && r-coins[i][0]+1 >= k { + l0, r0, c0 = coins[i][0], coins[i][1], coins[i][2] + ans = max64(ans, total+int64(max(k+l0-l, 0))*int64(c)) + total -= int64(r0-l0+1) * int64(c0) + i++ + } + + total += int64(r-l+1) * int64(c) + + if i < n && coins[i][0] != l0 { + startL := r - k + 1 + ans = max64(ans, total+int64(max(r0-startL+1, 0))*int64(c0)) + } + } + if total > ans { + ans = total + } + return ans +} + +func max64(a, b int64) int64 { + if a > b { + return a + } + return b +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} +``` +#### Rust + +```rust +use std::cmp::{min, max}; +fn f(coins: &[(i32, i32, i32)], k: i32) -> i64 { + let mut result = 0; + let mut sum = 0; + let mut r = 0; + + for l in 0..coins.len() { + while r < coins.len() && coins[l].0 + k > coins[r].1 { + sum += (coins[r].1 - coins[r].0 + 1) as i64 * coins[r].2 as i64; + r += 1; + } + result = max(result, sum); + if r == coins.len() { + break; + } + let cnt = coins[l].0 + k - coins[r].0; + result = max(result, sum + max(cnt, 0) as i64 * coins[r].2 as i64); + sum -= (coins[l].1 - coins[l].0 + 1) as i64 * coins[l].2 as i64; + } + + result +} + +impl Solution { + pub fn maximum_coins(mut coins: Vec>, k: i32) -> i64 { + let mut coins: Vec<_> = coins.into_iter() + .map(|xs| (xs[0], xs[1], xs[2])) + .collect(); + coins.sort(); + let a = f(&coins, k); + coins.reverse(); + for i in 0..coins.len() { + (coins[i].0, coins[i].1) = (-coins[i].1, -coins[i].0); + } + let b = f(&coins, k); + + max(a, b) + } +} ``` diff --git a/solution/3400-3499/3413.Maximum Coins From K Consecutive Bags/Solution.cpp b/solution/3400-3499/3413.Maximum Coins From K Consecutive Bags/Solution.cpp new file mode 100644 index 0000000000000..aff067e232f06 --- /dev/null +++ b/solution/3400-3499/3413.Maximum Coins From K Consecutive Bags/Solution.cpp @@ -0,0 +1,63 @@ +class Solution { +private: + struct interval { + int start = -1, end = -1, value = 0; + + interval() = default; + interval(int _start, int _end, int _value) + : start(_start) + , end(_end) + , value(_value) {} + + bool operator<(const interval& other) const { + return start < other.start || (start == other.start && end < other.end); + } + int64_t cost() const { return int64_t(value) * (end - start + 1); } + int64_t cost(int len) const { return int64_t(value) * len; } + }; + +public: + long long maximumCoins(vector>& coins, int k) { + int N = int(coins.size()); + vector A(N); + + for (int i = 0; i < N; i++) A[i] = {coins[i][0], coins[i][1], coins[i][2]}; + sort(A.begin(), A.end()); + + int64_t ans = 0LL; + { + int64_t value = 0LL; + int right = 0; + for (int left = 0; left < N; left++) { + while (right < N && A[right].end - A[left].start < k) { + value += A[right].cost(); + ++right; + } + + if (right < N) { + int64_t extra = (A[right].start - A[left].start <= k) ? A[right].cost(k - A[right].start + A[left].start) : 0LL; + ans = max(ans, value + extra); + } + + value -= A[left].cost(); + } + } + + { + int64_t value = 0LL; + int left = 0; + for (int right = 0; right < N; right++) { + value += A[right].cost(); + while (A[right].end - A[left].end >= k) { + value -= A[left].cost(); + left++; + } + + int64_t extra = (A[right].end - A[left].start >= k) ? A[left].cost(A[right].end - A[left].start - k + 1) : 0LL; + ans = max(ans, value - extra); + } + } + + return ans; + } +}; diff --git a/solution/3400-3499/3413.Maximum Coins From K Consecutive Bags/Solution.go b/solution/3400-3499/3413.Maximum Coins From K Consecutive Bags/Solution.go new file mode 100644 index 0000000000000..7aa7a7021e03d --- /dev/null +++ b/solution/3400-3499/3413.Maximum Coins From K Consecutive Bags/Solution.go @@ -0,0 +1,47 @@ +func maximumCoins(coins [][]int, k int) int64 { + sort.Slice(coins, func(i, j int) bool { + return coins[i][0] < coins[j][0] + }) + + n := len(coins) + var total int64 = 0 + var ans int64 = 0 + i := 0 + l0, r0, c0 := coins[0][0], coins[0][1], coins[0][2] + + for _, seg := range coins { + l, r, c := seg[0], seg[1], seg[2] + + for i < n && r-coins[i][0]+1 >= k { + l0, r0, c0 = coins[i][0], coins[i][1], coins[i][2] + ans = max64(ans, total+int64(max(k+l0-l, 0))*int64(c)) + total -= int64(r0-l0+1) * int64(c0) + i++ + } + + total += int64(r-l+1) * int64(c) + + if i < n && coins[i][0] != l0 { + startL := r - k + 1 + ans = max64(ans, total+int64(max(r0-startL+1, 0))*int64(c0)) + } + } + if total > ans { + ans = total + } + return ans +} + +func max64(a, b int64) int64 { + if a > b { + return a + } + return b +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} diff --git a/solution/3400-3499/3413.Maximum Coins From K Consecutive Bags/Solution.py b/solution/3400-3499/3413.Maximum Coins From K Consecutive Bags/Solution.py new file mode 100644 index 0000000000000..b6d207cb67157 --- /dev/null +++ b/solution/3400-3499/3413.Maximum Coins From K Consecutive Bags/Solution.py @@ -0,0 +1,20 @@ +class Solution: + def maximumCoins(self, coins: List[List[int]], k: int) -> int: + coins.sort(key=itemgetter(0)) + i, total, ans, n = 0, 0, 0, len(coins) + l0, r0, c0 = coins[0] + print(coins) + for l, r, c in coins: + while i < n and r - coins[i][0] + 1 >= k: + # print(r,coins[i][0],total) + l0, r0, c0 = coins[i] + ans = max(total + max(k + l0 - l, 0) * c, ans) + total -= (r0 - l0 + 1) * c0 + i += 1 + + total += (r - l + 1) * c + # print(total,l,r) + if i < n and coins[i][0] != l0: + start_l = r - k + 1 + ans = max(total + max(r0 - start_l + 1, 0) * c0, ans) + return max(ans, total) diff --git a/solution/3400-3499/3413.Maximum Coins From K Consecutive Bags/Solution.rs b/solution/3400-3499/3413.Maximum Coins From K Consecutive Bags/Solution.rs new file mode 100644 index 0000000000000..a4040759c9357 --- /dev/null +++ b/solution/3400-3499/3413.Maximum Coins From K Consecutive Bags/Solution.rs @@ -0,0 +1,37 @@ +use std::cmp::{max, min}; +fn f(coins: &[(i32, i32, i32)], k: i32) -> i64 { + let mut result = 0; + let mut sum = 0; + let mut r = 0; + + for l in 0..coins.len() { + while r < coins.len() && coins[l].0 + k > coins[r].1 { + sum += (coins[r].1 - coins[r].0 + 1) as i64 * coins[r].2 as i64; + r += 1; + } + result = max(result, sum); + if r == coins.len() { + break; + } + let cnt = coins[l].0 + k - coins[r].0; + result = max(result, sum + max(cnt, 0) as i64 * coins[r].2 as i64); + sum -= (coins[l].1 - coins[l].0 + 1) as i64 * coins[l].2 as i64; + } + + result +} + +impl Solution { + pub fn maximum_coins(mut coins: Vec>, k: i32) -> i64 { + let mut coins: Vec<_> = coins.into_iter().map(|xs| (xs[0], xs[1], xs[2])).collect(); + coins.sort(); + let a = f(&coins, k); + coins.reverse(); + for i in 0..coins.len() { + (coins[i].0, coins[i].1) = (-coins[i].1, -coins[i].0); + } + let b = f(&coins, k); + + max(a, b) + } +} diff --git a/solution/3600-3699/3603.Minimum Cost Path with Alternating Directions II/README.md b/solution/3600-3699/3603.Minimum Cost Path with Alternating Directions II/README.md index 20e05c172a23a..fb7194e63ade6 100644 --- a/solution/3600-3699/3603.Minimum Cost Path with Alternating Directions II/README.md +++ b/solution/3600-3699/3603.Minimum Cost Path with Alternating Directions II/README.md @@ -127,7 +127,34 @@ tags: #### Python3 ```python - +class Solution: + def minCost(self, m: int, n: int, waitCost: List[List[int]]) -> int: + directions = [(1, 0), (0, 1)] # only down and right + visited = dict() + + heap = [(1 * 1, 0, 0, 1)] # (cost, i, j, time) + + while heap: + cost, i, j, time = heapq.heappop(heap) + + if (i, j, time % 2) in visited and visited[(i, j, time % 2)] <= cost: + continue + visited[(i, j, time % 2)] = cost + + if i == m - 1 and j == n - 1: + return cost + + if time % 2 == 1: # move step + for dx, dy in directions: + ni, nj = i + dx, j + dy + if 0 <= ni < m and 0 <= nj < n: + next_cost = cost + (ni + 1) * (nj + 1) + heapq.heappush(heap, (next_cost, ni, nj, time + 1)) + else: # wait step + next_cost = cost + waitCost[i][j] + heapq.heappush(heap, (next_cost, i, j, time + 1)) + + return -1 ``` #### Java @@ -145,7 +172,25 @@ tags: #### Go ```go - +func minCost(m int, n int, cost [][]int) int64 { + dp := make([]int64, n) + for i := 0; i < n; i++ { + dp[i] = int64(i + 1) + } + for i := 1; i < n; i++ { + dp[i] += dp[i-1] + int64(cost[0][i]) + } + + for y := 1; y < m; y++ { + dp[0] += int64(cost[y][0]) + int64(y+1) + for x := 1; x < n; x++ { + enter := int64(y+1) * int64(x+1) + dp[x] = min(dp[x], dp[x-1]) + int64(cost[y][x]) + enter + } + } + + return dp[n-1] - int64(cost[m-1][n-1]) +} ``` diff --git a/solution/3600-3699/3603.Minimum Cost Path with Alternating Directions II/README_EN.md b/solution/3600-3699/3603.Minimum Cost Path with Alternating Directions II/README_EN.md index 78b8d382f4272..0b680f2fc7bfc 100644 --- a/solution/3600-3699/3603.Minimum Cost Path with Alternating Directions II/README_EN.md +++ b/solution/3600-3699/3603.Minimum Cost Path with Alternating Directions II/README_EN.md @@ -125,7 +125,34 @@ tags: #### Python3 ```python - +class Solution: + def minCost(self, m: int, n: int, waitCost: List[List[int]]) -> int: + directions = [(1, 0), (0, 1)] # only down and right + visited = dict() + + heap = [(1 * 1, 0, 0, 1)] # (cost, i, j, time) + + while heap: + cost, i, j, time = heapq.heappop(heap) + + if (i, j, time % 2) in visited and visited[(i, j, time % 2)] <= cost: + continue + visited[(i, j, time % 2)] = cost + + if i == m - 1 and j == n - 1: + return cost + + if time % 2 == 1: # move step + for dx, dy in directions: + ni, nj = i + dx, j + dy + if 0 <= ni < m and 0 <= nj < n: + next_cost = cost + (ni + 1) * (nj + 1) + heapq.heappush(heap, (next_cost, ni, nj, time + 1)) + else: # wait step + next_cost = cost + waitCost[i][j] + heapq.heappush(heap, (next_cost, i, j, time + 1)) + + return -1 ``` #### Java @@ -143,7 +170,25 @@ tags: #### Go ```go - +func minCost(m int, n int, cost [][]int) int64 { + dp := make([]int64, n) + for i := 0; i < n; i++ { + dp[i] = int64(i + 1) + } + for i := 1; i < n; i++ { + dp[i] += dp[i-1] + int64(cost[0][i]) + } + + for y := 1; y < m; y++ { + dp[0] += int64(cost[y][0]) + int64(y+1) + for x := 1; x < n; x++ { + enter := int64(y+1) * int64(x+1) + dp[x] = min(dp[x], dp[x-1]) + int64(cost[y][x]) + enter + } + } + + return dp[n-1] - int64(cost[m-1][n-1]) +} ``` diff --git a/solution/3600-3699/3603.Minimum Cost Path with Alternating Directions II/Solution.go b/solution/3600-3699/3603.Minimum Cost Path with Alternating Directions II/Solution.go new file mode 100644 index 0000000000000..7f5110a3f8f3d --- /dev/null +++ b/solution/3600-3699/3603.Minimum Cost Path with Alternating Directions II/Solution.go @@ -0,0 +1,26 @@ +func minCost(m int, n int, cost [][]int) int64 { + dp := make([]int64, n) + for i := 0; i < n; i++ { + dp[i] = int64(i + 1) + } + for i := 1; i < n; i++ { + dp[i] += dp[i-1] + int64(cost[0][i]) + } + + for y := 1; y < m; y++ { + dp[0] += int64(cost[y][0]) + int64(y+1) + for x := 1; x < n; x++ { + enter := int64(y+1) * int64(x+1) + dp[x] = min64(dp[x], dp[x-1]) + int64(cost[y][x]) + enter + } + } + + return dp[n-1] - int64(cost[m-1][n-1]) +} + +func min64(a, b int64) int64 { + if a < b { + return a + } + return b +} diff --git a/solution/3600-3699/3603.Minimum Cost Path with Alternating Directions II/Solution.py b/solution/3600-3699/3603.Minimum Cost Path with Alternating Directions II/Solution.py new file mode 100644 index 0000000000000..a6367b718fa70 --- /dev/null +++ b/solution/3600-3699/3603.Minimum Cost Path with Alternating Directions II/Solution.py @@ -0,0 +1,28 @@ +class Solution: + def minCost(self, m: int, n: int, waitCost: List[List[int]]) -> int: + directions = [(1, 0), (0, 1)] # only down and right + visited = dict() + + heap = [(1 * 1, 0, 0, 1)] # (cost, i, j, time) + + while heap: + cost, i, j, time = heapq.heappop(heap) + + if (i, j, time % 2) in visited and visited[(i, j, time % 2)] <= cost: + continue + visited[(i, j, time % 2)] = cost + + if i == m - 1 and j == n - 1: + return cost + + if time % 2 == 1: # move step + for dx, dy in directions: + ni, nj = i + dx, j + dy + if 0 <= ni < m and 0 <= nj < n: + next_cost = cost + (ni + 1) * (nj + 1) + heapq.heappush(heap, (next_cost, ni, nj, time + 1)) + else: # wait step + next_cost = cost + waitCost[i][j] + heapq.heappush(heap, (next_cost, i, j, time + 1)) + + return -1 diff --git a/solution/3600-3699/3604.Minimum Time to Reach Destination in Directed Graph/README.md b/solution/3600-3699/3604.Minimum Time to Reach Destination in Directed Graph/README.md index 030dc56097403..3a8f2c8a85d6a 100644 --- a/solution/3600-3699/3604.Minimum Time to Reach Destination in Directed Graph/README.md +++ b/solution/3600-3699/3604.Minimum Time to Reach Destination in Directed Graph/README.md @@ -120,7 +120,29 @@ tags: #### Python3 ```python - +class Solution: + def minTime(self, n: int, edges: List[List[int]]) -> int: + minReachTime = [inf] * n + minReachTime[0] = 0 + + nodeEdges = [[] for _ in range(n)] + for edge in edges: + nodeEdges[edge[0]].append(edge) + + reachTimeHeap = [(0, 0)] + while reachTimeHeap: + curTime, node = heappop(reachTimeHeap) + if node == n - 1: + return curTime + + for edge in nodeEdges[node]: + if curTime <= edge[3]: + destTime = max(curTime, edge[2]) + 1 + if minReachTime[edge[1]] > destTime: + minReachTime[edge[1]] = destTime + heappush(reachTimeHeap, (destTime, edge[1])) + + return -1 ``` #### Java @@ -132,13 +154,143 @@ tags: #### C++ ```cpp - +class Solution { + vector>> adj; + vector sol; + priority_queue ,vector>,greater<>> pq; + void pushNeighbours(int node,int curr){ + for(auto it : adj[node]){ + int temp = it[0] , start = it[1],end = it[2],newTime = curr+1; + if(curr>& edges) { + adj = vector>>(n); + for(auto it: edges) + adj[it[0]].push_back({it[1],it[2],it[3]}); + sol = vector (n,INT_MAX); + sol[0]=0; + for(pq.push({0,0});!pq.empty();pq.pop()) + pushNeighbours(pq.top().second,pq.top().first); + if(sol[n-1] == INT_MAX) return -1; + return sol[n-1]; + } +}; +const auto __ = []() { + struct ___ { + static void _() { + std::ofstream("display_runtime.txt") << 0 << '\n'; + std::ofstream("display_memory.txt") << 0 << '\n'; + } + }; + std::atexit(&___::_); + return 0; +}(); ``` #### Go ```go - +import "container/heap" + +func minTime(n int, edges [][]int) int { + graph := make([][][3]int, n) + for _, edge := range edges { + u, v, start, end := edge[0], edge[1], edge[2], edge[3] + graph[u] = append(graph[u], [3]int{v, start, end}) + } + + dist := make([]int, n) + for i := range dist { + dist[i] = -1 + } + dist[0] = 0 + + pq := &PriorityQueue{} + heap.Init(pq) + heap.Push(pq, &Item{value: 0, priority: 0}) + + for pq.Len() > 0 { + item := heap.Pop(pq).(*Item) + u := item.value + d := item.priority + + if d > dist[u] && dist[u] != -1{ + continue + } + + + if u == n-1{ + continue + } + + + for _, edge := range graph[u] { + v, start, end := edge[0], edge[1], edge[2] + + wait := 0 + if d < start { + wait = start - d + } + + if d + wait <= end { + newDist := d + wait + 1 + if dist[v] == -1 || newDist < dist[v] { + dist[v] = newDist + heap.Push(pq, &Item{value: v, priority: newDist}) + } + } + } + } + + return dist[n-1] +} + +type Item struct { + value int // The value of the item; arbitrary. + priority int // The priority of the item in the queue. + // The index is needed to update during heap operations. It is + // maintained by the heap.Interface methods. + index int // The index of the item in the heap. +} + +// A PriorityQueue implements heap.Interface and holds Items. +type PriorityQueue []*Item + +func (pq PriorityQueue) Len() int { return len(pq) } + +func (pq PriorityQueue) Less(i, j int) bool { + // We want Pop to give us the lowest, not highest, priority so we use less than here. + return pq[i].priority < pq[j].priority +} + +func (pq PriorityQueue) Swap(i, j int) { + pq[i], pq[j] = pq[j], pq[i] + pq[i].index = i + pq[j].index = j +} + +func (pq *PriorityQueue) Push(x any) { + n := len(*pq) + item := x.(*Item) + item.index = n + *pq = append(*pq, item) +} + +func (pq *PriorityQueue) Pop() any { + old := *pq + n := len(old) + item := old[n-1] + old[n-1] = nil // avoid memory leak + item.index = -1 // for safety + *pq = old[0 : n-1] + return item +} ``` diff --git a/solution/3600-3699/3604.Minimum Time to Reach Destination in Directed Graph/README_EN.md b/solution/3600-3699/3604.Minimum Time to Reach Destination in Directed Graph/README_EN.md index 186d3dd97354f..a90fef04257ee 100644 --- a/solution/3600-3699/3604.Minimum Time to Reach Destination in Directed Graph/README_EN.md +++ b/solution/3600-3699/3604.Minimum Time to Reach Destination in Directed Graph/README_EN.md @@ -117,7 +117,29 @@ tags: #### Python3 ```python - +class Solution: + def minTime(self, n: int, edges: List[List[int]]) -> int: + minReachTime = [inf] * n + minReachTime[0] = 0 + + nodeEdges = [[] for _ in range(n)] + for edge in edges: + nodeEdges[edge[0]].append(edge) + + reachTimeHeap = [(0, 0)] + while reachTimeHeap: + curTime, node = heappop(reachTimeHeap) + if node == n - 1: + return curTime + + for edge in nodeEdges[node]: + if curTime <= edge[3]: + destTime = max(curTime, edge[2]) + 1 + if minReachTime[edge[1]] > destTime: + minReachTime[edge[1]] = destTime + heappush(reachTimeHeap, (destTime, edge[1])) + + return -1 ``` #### Java @@ -129,13 +151,143 @@ tags: #### C++ ```cpp - +class Solution { + vector>> adj; + vector sol; + priority_queue ,vector>,greater<>> pq; + void pushNeighbours(int node,int curr){ + for(auto it : adj[node]){ + int temp = it[0] , start = it[1],end = it[2],newTime = curr+1; + if(curr>& edges) { + adj = vector>>(n); + for(auto it: edges) + adj[it[0]].push_back({it[1],it[2],it[3]}); + sol = vector (n,INT_MAX); + sol[0]=0; + for(pq.push({0,0});!pq.empty();pq.pop()) + pushNeighbours(pq.top().second,pq.top().first); + if(sol[n-1] == INT_MAX) return -1; + return sol[n-1]; + } +}; +const auto __ = []() { + struct ___ { + static void _() { + std::ofstream("display_runtime.txt") << 0 << '\n'; + std::ofstream("display_memory.txt") << 0 << '\n'; + } + }; + std::atexit(&___::_); + return 0; +}(); ``` #### Go ```go - +import "container/heap" + +func minTime(n int, edges [][]int) int { + graph := make([][][3]int, n) + for _, edge := range edges { + u, v, start, end := edge[0], edge[1], edge[2], edge[3] + graph[u] = append(graph[u], [3]int{v, start, end}) + } + + dist := make([]int, n) + for i := range dist { + dist[i] = -1 + } + dist[0] = 0 + + pq := &PriorityQueue{} + heap.Init(pq) + heap.Push(pq, &Item{value: 0, priority: 0}) + + for pq.Len() > 0 { + item := heap.Pop(pq).(*Item) + u := item.value + d := item.priority + + if d > dist[u] && dist[u] != -1{ + continue + } + + + if u == n-1{ + continue + } + + + for _, edge := range graph[u] { + v, start, end := edge[0], edge[1], edge[2] + + wait := 0 + if d < start { + wait = start - d + } + + if d + wait <= end { + newDist := d + wait + 1 + if dist[v] == -1 || newDist < dist[v] { + dist[v] = newDist + heap.Push(pq, &Item{value: v, priority: newDist}) + } + } + } + } + + return dist[n-1] +} + +type Item struct { + value int // The value of the item; arbitrary. + priority int // The priority of the item in the queue. + // The index is needed to update during heap operations. It is + // maintained by the heap.Interface methods. + index int // The index of the item in the heap. +} + +// A PriorityQueue implements heap.Interface and holds Items. +type PriorityQueue []*Item + +func (pq PriorityQueue) Len() int { return len(pq) } + +func (pq PriorityQueue) Less(i, j int) bool { + // We want Pop to give us the lowest, not highest, priority so we use less than here. + return pq[i].priority < pq[j].priority +} + +func (pq PriorityQueue) Swap(i, j int) { + pq[i], pq[j] = pq[j], pq[i] + pq[i].index = i + pq[j].index = j +} + +func (pq *PriorityQueue) Push(x any) { + n := len(*pq) + item := x.(*Item) + item.index = n + *pq = append(*pq, item) +} + +func (pq *PriorityQueue) Pop() any { + old := *pq + n := len(old) + item := old[n-1] + old[n-1] = nil // avoid memory leak + item.index = -1 // for safety + *pq = old[0 : n-1] + return item +} ``` diff --git a/solution/3600-3699/3604.Minimum Time to Reach Destination in Directed Graph/Solution.cpp b/solution/3600-3699/3604.Minimum Time to Reach Destination in Directed Graph/Solution.cpp new file mode 100644 index 0000000000000..83c2d71271897 --- /dev/null +++ b/solution/3600-3699/3604.Minimum Time to Reach Destination in Directed Graph/Solution.cpp @@ -0,0 +1,38 @@ +class Solution { + vector>> adj; + vector sol; + priority_queue, vector>, greater<>> pq; + void pushNeighbours(int node, int curr) { + for (auto it : adj[node]) { + int temp = it[0], start = it[1], end = it[2], newTime = curr + 1; + if (curr < start) newTime = start + 1; + if (newTime < sol[temp] && newTime - 1 <= end) { + pq.push({newTime, temp}); + sol[temp] = newTime; + } + } + } + +public: + int minTime(int n, vector>& edges) { + adj = vector>>(n); + for (auto it : edges) + adj[it[0]].push_back({it[1], it[2], it[3]}); + sol = vector(n, INT_MAX); + sol[0] = 0; + for (pq.push({0, 0}); !pq.empty(); pq.pop()) + pushNeighbours(pq.top().second, pq.top().first); + if (sol[n - 1] == INT_MAX) return -1; + return sol[n - 1]; + } +}; +const auto __ = []() { + struct ___ { + static void _() { + std::ofstream("display_runtime.txt") << 0 << '\n'; + std::ofstream("display_memory.txt") << 0 << '\n'; + } + }; + std::atexit(&___::_); + return 0; +}(); diff --git a/solution/3600-3699/3604.Minimum Time to Reach Destination in Directed Graph/Solution.go b/solution/3600-3699/3604.Minimum Time to Reach Destination in Directed Graph/Solution.go new file mode 100644 index 0000000000000..d67c03354363b --- /dev/null +++ b/solution/3600-3699/3604.Minimum Time to Reach Destination in Directed Graph/Solution.go @@ -0,0 +1,95 @@ +import "container/heap" + +func minTime(n int, edges [][]int) int { + graph := make([][][3]int, n) + for _, edge := range edges { + u, v, start, end := edge[0], edge[1], edge[2], edge[3] + graph[u] = append(graph[u], [3]int{v, start, end}) + } + + dist := make([]int, n) + for i := range dist { + dist[i] = -1 + } + dist[0] = 0 + + pq := &PriorityQueue{} + heap.Init(pq) + heap.Push(pq, &Item{value: 0, priority: 0}) + + for pq.Len() > 0 { + item := heap.Pop(pq).(*Item) + u := item.value + d := item.priority + + if d > dist[u] && dist[u] != -1{ + continue + } + + + if u == n-1{ + continue + } + + + for _, edge := range graph[u] { + v, start, end := edge[0], edge[1], edge[2] + + wait := 0 + if d < start { + wait = start - d + } + + if d + wait <= end { + newDist := d + wait + 1 + if dist[v] == -1 || newDist < dist[v] { + dist[v] = newDist + heap.Push(pq, &Item{value: v, priority: newDist}) + } + } + } + } + + return dist[n-1] +} + +type Item struct { + value int // The value of the item; arbitrary. + priority int // The priority of the item in the queue. + // The index is needed to update during heap operations. It is + // maintained by the heap.Interface methods. + index int // The index of the item in the heap. +} + +// A PriorityQueue implements heap.Interface and holds Items. +type PriorityQueue []*Item + +func (pq PriorityQueue) Len() int { return len(pq) } + +func (pq PriorityQueue) Less(i, j int) bool { + // We want Pop to give us the lowest, not highest, priority so we use less than here. + return pq[i].priority < pq[j].priority +} + +func (pq PriorityQueue) Swap(i, j int) { + pq[i], pq[j] = pq[j], pq[i] + pq[i].index = i + pq[j].index = j +} + +func (pq *PriorityQueue) Push(x any) { + n := len(*pq) + item := x.(*Item) + item.index = n + *pq = append(*pq, item) +} + +func (pq *PriorityQueue) Pop() any { + old := *pq + n := len(old) + item := old[n-1] + old[n-1] = nil // avoid memory leak + item.index = -1 // for safety + *pq = old[0 : n-1] + return item +} diff --git a/solution/3600-3699/3604.Minimum Time to Reach Destination in Directed Graph/Solution.py b/solution/3600-3699/3604.Minimum Time to Reach Destination in Directed Graph/Solution.py new file mode 100644 index 0000000000000..75a817dd24ae7 --- /dev/null +++ b/solution/3600-3699/3604.Minimum Time to Reach Destination in Directed Graph/Solution.py @@ -0,0 +1,23 @@ +class Solution: + def minTime(self, n: int, edges: List[List[int]]) -> int: + minReachTime = [inf] * n + minReachTime[0] = 0 + + nodeEdges = [[] for _ in range(n)] + for edge in edges: + nodeEdges[edge[0]].append(edge) + + reachTimeHeap = [(0, 0)] + while reachTimeHeap: + curTime, node = heappop(reachTimeHeap) + if node == n - 1: + return curTime + + for edge in nodeEdges[node]: + if curTime <= edge[3]: + destTime = max(curTime, edge[2]) + 1 + if minReachTime[edge[1]] > destTime: + minReachTime[edge[1]] = destTime + heappush(reachTimeHeap, (destTime, edge[1])) + + return -1