Skip to content

Commit f847c0f

Browse files
authored
feat: add solutions to lc problem: No.2714 (#1757)
1 parent 59b0735 commit f847c0f

File tree

6 files changed

+454
-8
lines changed

6 files changed

+454
-8
lines changed

solution/2700-2799/2714.Find Shortest Path with K Hops/README.md

+155-4
Original file line numberDiff line numberDiff line change
@@ -63,34 +63,185 @@
6363

6464
<!-- 这里可写通用的实现逻辑 -->
6565

66+
**方法一:Dijkstra 算法**
67+
68+
我们先根据给定的边构造出图 $g$,其中 $g[u]$ 表示节点 $u$ 的所有邻居节点以及对应的边权重。
69+
70+
然后我们使用 Dijkstra 算法求出从节点 $s$ 到节点 $d$ 的最短路径,但是在这里我们需要对 Dijkstra 算法进行一些修改:
71+
72+
- 我们需要记录每个节点 $u$ 到节点 $d$ 的最短路径长度,但是由于我们可以最多跨越 $k$ 条边,所以我们需要记录每个节点 $u$ 到节点 $d$ 的最短路径长度,以及跨越的边数 $t$,即 $dist[u][t]$ 表示从节点 $u$ 到节点 $d$ 的最短路径长度,且跨越的边数为 $t$。
73+
- 我们需要使用优先队列来维护当前的最短路径,但是由于我们需要记录跨越的边数,所以我们需要使用三元组 $(dis, u, t)$ 来表示当前的最短路径,其中 $dis$ 表示当前的最短路径长度,而 $u$ 和 $t$ 分别表示当前的节点和跨越的边数。
74+
75+
最后我们只需要返回 $dist[d][0..k]$ 中的最小值即可。
76+
77+
时间复杂度 $O(n^2 \times \log n)$,空间复杂度 $O(n \times k)$。其中 $n$ 表示节点数,而 $k$ 表示最多跨越的边数。
78+
6679
<!-- tabs:start -->
6780

6881
### **Python3**
6982

7083
<!-- 这里可写当前语言的特殊实现逻辑 -->
7184

7285
```python
73-
86+
class Solution:
87+
def shortestPathWithHops(self, n: int, edges: List[List[int]], s: int, d: int, k: int) -> int:
88+
g = [[] for _ in range(n)]
89+
for u, v, w in edges:
90+
g[u].append((v, w))
91+
g[v].append((u, w))
92+
dist = [[inf] * (k + 1) for _ in range(n)]
93+
dist[s][0] = 0
94+
pq = [(0, s, 0)]
95+
while pq:
96+
dis, u, t = heappop(pq)
97+
for v, w in g[u]:
98+
if t + 1 <= k and dist[v][t + 1] > dis:
99+
dist[v][t + 1] = dis
100+
heappush(pq, (dis, v, t + 1))
101+
if dist[v][t] > dis + w:
102+
dist[v][t] = dis + w
103+
heappush(pq, (dis + w, v, t))
104+
return int(min(dist[d]))
74105
```
75106

76107
### **Java**
77108

78109
<!-- 这里可写当前语言的特殊实现逻辑 -->
79110

80111
```java
81-
112+
class Solution {
113+
public int shortestPathWithHops(int n, int[][] edges, int s, int d, int k) {
114+
List<int[]>[] g = new List[n];
115+
Arrays.setAll(g, i -> new ArrayList<>());
116+
for (int[] e : edges) {
117+
int u = e[0], v = e[1], w = e[2];
118+
g[u].add(new int[] {v, w});
119+
g[v].add(new int[] {u, w});
120+
}
121+
PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> a[0] - b[0]);
122+
pq.offer(new int[] {0, s, 0});
123+
int[][] dist = new int[n][k + 1];
124+
final int inf = 1 << 30;
125+
for (int[] e : dist) {
126+
Arrays.fill(e, inf);
127+
}
128+
dist[s][0] = 0;
129+
while (!pq.isEmpty()) {
130+
int[] p = pq.poll();
131+
int dis = p[0], u = p[1], t = p[2];
132+
for (int[] e : g[u]) {
133+
int v = e[0], w = e[1];
134+
if (t + 1 <= k && dist[v][t + 1] > dis) {
135+
dist[v][t + 1] = dis;
136+
pq.offer(new int[] {dis, v, t + 1});
137+
}
138+
if (dist[v][t] > dis + w) {
139+
dist[v][t] = dis + w;
140+
pq.offer(new int[] {dis + w, v, t});
141+
}
142+
}
143+
}
144+
int ans = inf;
145+
for (int i = 0; i <= k; ++i) {
146+
ans = Math.min(ans, dist[d][i]);
147+
}
148+
return ans;
149+
}
150+
}
82151
```
83152

84153
### **C++**
85154

86155
```cpp
87-
156+
class Solution {
157+
public:
158+
int shortestPathWithHops(int n, vector<vector<int>>& edges, int s, int d, int k) {
159+
vector<pair<int, int>> g[n];
160+
for (auto& e : edges) {
161+
int u = e[0], v = e[1], w = e[2];
162+
g[u].emplace_back(v, w);
163+
g[v].emplace_back(u, w);
164+
}
165+
priority_queue<tuple<int, int, int>, vector<tuple<int, int, int>>, greater<tuple<int, int, int>>> pq;
166+
pq.emplace(0, s, 0);
167+
int dist[n][k + 1];
168+
memset(dist, 0x3f, sizeof(dist));
169+
dist[s][0] = 0;
170+
while (!pq.empty()) {
171+
auto [dis, u, t] = pq.top();
172+
pq.pop();
173+
for (auto [v, w] : g[u]) {
174+
if (t + 1 <= k && dist[v][t + 1] > dis) {
175+
dist[v][t + 1] = dis;
176+
pq.emplace(dis, v, t + 1);
177+
}
178+
if (dist[v][t] > dis + w) {
179+
dist[v][t] = dis + w;
180+
pq.emplace(dis + w, v, t);
181+
}
182+
}
183+
}
184+
return *min_element(dist[d], dist[d] + k + 1);
185+
}
186+
};
88187
```
89188
90189
### **Go**
91190
92191
```go
93-
192+
func shortestPathWithHops(n int, edges [][]int, s int, d int, k int) int {
193+
g := make([][][2]int, n)
194+
for _, e := range edges {
195+
u, v, w := e[0], e[1], e[2]
196+
g[u] = append(g[u], [2]int{v, w})
197+
g[v] = append(g[v], [2]int{u, w})
198+
}
199+
pq := hp{{0, s, 0}}
200+
dist := make([][]int, n)
201+
for i := range dist {
202+
dist[i] = make([]int, k+1)
203+
for j := range dist[i] {
204+
dist[i][j] = math.MaxInt32
205+
}
206+
}
207+
dist[s][0] = 0
208+
for len(pq) > 0 {
209+
p := heap.Pop(&pq).(tuple)
210+
dis, u, t := p.dis, p.u, p.t
211+
for _, e := range g[u] {
212+
v, w := e[0], e[1]
213+
if t+1 <= k && dist[v][t+1] > dis {
214+
dist[v][t+1] = dis
215+
heap.Push(&pq, tuple{dis, v, t + 1})
216+
}
217+
if dist[v][t] > dis+w {
218+
dist[v][t] = dis + w
219+
heap.Push(&pq, tuple{dis + w, v, t})
220+
}
221+
}
222+
}
223+
ans := math.MaxInt32
224+
for i := 0; i <= k; i++ {
225+
ans = min(ans, dist[d][i])
226+
}
227+
return ans
228+
}
229+
230+
func min(a, b int) int {
231+
if a < b {
232+
return a
233+
}
234+
return b
235+
}
236+
237+
type tuple struct{ dis, u, t int }
238+
type hp []tuple
239+
240+
func (h hp) Len() int { return len(h) }
241+
func (h hp) Less(i, j int) bool { return h[i].dis < h[j].dis }
242+
func (h hp) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
243+
func (h *hp) Push(v any) { *h = append(*h, v.(tuple)) }
244+
func (h *hp) Pop() any { a := *h; v := a[len(a)-1]; *h = a[:len(a)-1]; return v }
94245
```
95246

96247
### **...**

solution/2700-2799/2714.Find Shortest Path with K Hops/README_EN.md

+155-4
Original file line numberDiff line numberDiff line change
@@ -57,30 +57,181 @@
5757

5858
## Solutions
5959

60+
**Solution 1: Dijkstra Algorithm**
61+
62+
First, we construct a graph $g$ based on the given edges, where $g[u]$ represents all neighboring nodes of node $u$ and their corresponding edge weights.
63+
64+
Then, we use Dijkstra's algorithm to find the shortest path from node $s$ to node $d$. However, we need to make some modifications to Dijkstra's algorithm:
65+
66+
- We need to record the shortest path length from each node $u$ to node $d$, but since we can cross at most $k$ edges, we need to record the shortest path length from each node $u$ to node $d$ and the number of edges crossed $t$, i.e., $dist[u][t]$ represents the shortest path length from node $u$ to node $d$ and the number of edges crossed is $t$.
67+
- We need to use a priority queue to maintain the current shortest path, but since we need to record the number of edges crossed, we need to use a triple $(dis, u, t)$ to represent the current shortest path, where $dis$ represents the current shortest path length, and $u$ and $t$ represent the current node and the number of edges crossed, respectively.
68+
69+
Finally, we only need to return the minimum value in $dist[d][0..k]$.
70+
71+
The time complexity is $O(n^2 \times \log n)$, and the space complexity is $O(n \times k)$, where $n$ represents the number of nodes and $k$ represents the maximum number of edges crossed.
72+
6073
<!-- tabs:start -->
6174

6275
### **Python3**
6376

6477
```python
65-
78+
class Solution:
79+
def shortestPathWithHops(self, n: int, edges: List[List[int]], s: int, d: int, k: int) -> int:
80+
g = [[] for _ in range(n)]
81+
for u, v, w in edges:
82+
g[u].append((v, w))
83+
g[v].append((u, w))
84+
dist = [[inf] * (k + 1) for _ in range(n)]
85+
dist[s][0] = 0
86+
pq = [(0, s, 0)]
87+
while pq:
88+
dis, u, t = heappop(pq)
89+
for v, w in g[u]:
90+
if t + 1 <= k and dist[v][t + 1] > dis:
91+
dist[v][t + 1] = dis
92+
heappush(pq, (dis, v, t + 1))
93+
if dist[v][t] > dis + w:
94+
dist[v][t] = dis + w
95+
heappush(pq, (dis + w, v, t))
96+
return int(min(dist[d]))
6697
```
6798

6899
### **Java**
69100

70101
```java
71-
102+
class Solution {
103+
public int shortestPathWithHops(int n, int[][] edges, int s, int d, int k) {
104+
List<int[]>[] g = new List[n];
105+
Arrays.setAll(g, i -> new ArrayList<>());
106+
for (int[] e : edges) {
107+
int u = e[0], v = e[1], w = e[2];
108+
g[u].add(new int[] {v, w});
109+
g[v].add(new int[] {u, w});
110+
}
111+
PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> a[0] - b[0]);
112+
pq.offer(new int[] {0, s, 0});
113+
int[][] dist = new int[n][k + 1];
114+
final int inf = 1 << 30;
115+
for (int[] e : dist) {
116+
Arrays.fill(e, inf);
117+
}
118+
dist[s][0] = 0;
119+
while (!pq.isEmpty()) {
120+
int[] p = pq.poll();
121+
int dis = p[0], u = p[1], t = p[2];
122+
for (int[] e : g[u]) {
123+
int v = e[0], w = e[1];
124+
if (t + 1 <= k && dist[v][t + 1] > dis) {
125+
dist[v][t + 1] = dis;
126+
pq.offer(new int[] {dis, v, t + 1});
127+
}
128+
if (dist[v][t] > dis + w) {
129+
dist[v][t] = dis + w;
130+
pq.offer(new int[] {dis + w, v, t});
131+
}
132+
}
133+
}
134+
int ans = inf;
135+
for (int i = 0; i <= k; ++i) {
136+
ans = Math.min(ans, dist[d][i]);
137+
}
138+
return ans;
139+
}
140+
}
72141
```
73142

74143
### **C++**
75144

76145
```cpp
77-
146+
class Solution {
147+
public:
148+
int shortestPathWithHops(int n, vector<vector<int>>& edges, int s, int d, int k) {
149+
vector<pair<int, int>> g[n];
150+
for (auto& e : edges) {
151+
int u = e[0], v = e[1], w = e[2];
152+
g[u].emplace_back(v, w);
153+
g[v].emplace_back(u, w);
154+
}
155+
priority_queue<tuple<int, int, int>, vector<tuple<int, int, int>>, greater<tuple<int, int, int>>> pq;
156+
pq.emplace(0, s, 0);
157+
int dist[n][k + 1];
158+
memset(dist, 0x3f, sizeof(dist));
159+
dist[s][0] = 0;
160+
while (!pq.empty()) {
161+
auto [dis, u, t] = pq.top();
162+
pq.pop();
163+
for (auto [v, w] : g[u]) {
164+
if (t + 1 <= k && dist[v][t + 1] > dis) {
165+
dist[v][t + 1] = dis;
166+
pq.emplace(dis, v, t + 1);
167+
}
168+
if (dist[v][t] > dis + w) {
169+
dist[v][t] = dis + w;
170+
pq.emplace(dis + w, v, t);
171+
}
172+
}
173+
}
174+
return *min_element(dist[d], dist[d] + k + 1);
175+
}
176+
};
78177
```
79178
80179
### **Go**
81180
82181
```go
83-
182+
func shortestPathWithHops(n int, edges [][]int, s int, d int, k int) int {
183+
g := make([][][2]int, n)
184+
for _, e := range edges {
185+
u, v, w := e[0], e[1], e[2]
186+
g[u] = append(g[u], [2]int{v, w})
187+
g[v] = append(g[v], [2]int{u, w})
188+
}
189+
pq := hp{{0, s, 0}}
190+
dist := make([][]int, n)
191+
for i := range dist {
192+
dist[i] = make([]int, k+1)
193+
for j := range dist[i] {
194+
dist[i][j] = math.MaxInt32
195+
}
196+
}
197+
dist[s][0] = 0
198+
for len(pq) > 0 {
199+
p := heap.Pop(&pq).(tuple)
200+
dis, u, t := p.dis, p.u, p.t
201+
for _, e := range g[u] {
202+
v, w := e[0], e[1]
203+
if t+1 <= k && dist[v][t+1] > dis {
204+
dist[v][t+1] = dis
205+
heap.Push(&pq, tuple{dis, v, t + 1})
206+
}
207+
if dist[v][t] > dis+w {
208+
dist[v][t] = dis + w
209+
heap.Push(&pq, tuple{dis + w, v, t})
210+
}
211+
}
212+
}
213+
ans := math.MaxInt32
214+
for i := 0; i <= k; i++ {
215+
ans = min(ans, dist[d][i])
216+
}
217+
return ans
218+
}
219+
220+
func min(a, b int) int {
221+
if a < b {
222+
return a
223+
}
224+
return b
225+
}
226+
227+
type tuple struct{ dis, u, t int }
228+
type hp []tuple
229+
230+
func (h hp) Len() int { return len(h) }
231+
func (h hp) Less(i, j int) bool { return h[i].dis < h[j].dis }
232+
func (h hp) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
233+
func (h *hp) Push(v any) { *h = append(*h, v.(tuple)) }
234+
func (h *hp) Pop() any { a := *h; v := a[len(a)-1]; *h = a[:len(a)-1]; return v }
84235
```
85236

86237
### **...**

0 commit comments

Comments
 (0)