Skip to content

Commit 8a60b11

Browse files
authored
feat: add solutions to lc problem: No.1976 (doocs#2409)
No.1976.Number of Ways to Arrive at Destination
1 parent 61f2326 commit 8a60b11

File tree

7 files changed

+371
-188
lines changed

7 files changed

+371
-188
lines changed

solution/1900-1999/1976.Number of Ways to Arrive at Destination/README.md

+126-65
Original file line numberDiff line numberDiff line change
@@ -54,71 +54,73 @@
5454

5555
### 方法一:朴素 Dijkstra 算法
5656

57-
在求最短路的过程中顺便记录到达某个点最短路径的方案数。松弛优化时,如果发现有更优的路径,则方案数也赋值最优路径的前驱的方案数。如果发现与最优的路径长度相同,则累加当前前驱的方案数。
57+
我们定义以下几个数组,其中:
5858

59-
由于图有可能非常稠密,所以采用朴素的 Dijkstra 算法。
59+
- `g` 表示图的邻接矩阵,`g[i][j]` 表示点 `i` 到点 `j` 的最短路径长度,初始时全部为 $\infty$,而 `g[0][0]` 为 $0$;然后我们遍历 `roads`,将 `g[u][v]``g[v][u]` 更新为 `t`
60+
- `dist[i]` 表示从起点到点 `i` 的最短路径长度,初始时全部为 $\infty$,而 `dist[0]` 为 $0$;
61+
- `f[i]` 表示从起点到点 `i` 的最短路径的条数,初始时全部为 $0$,而 `f[0]` 为 $1$;
62+
- `vis[i]` 表示点 `i` 是否已经被访问过,初始时全部为 `False`
6063

61-
时间复杂度 $O(n^2)$
64+
然后,我们使用朴素 Dijkstra 算法求出从起点到终点的最短路径长度,过程中同时记录下每个点的最短路径的条数
6265

63-
> 注意:最短路的长度可能会超过 32 位整数的范围。
66+
最后,我们返回 `f[n - 1]` 即可。由于答案可能很大,我们需要对 $10^9 + 7$ 取模。
67+
68+
时间复杂度 $O(n^2)$,空间复杂度 $O(n^2)$。其中 $n$ 为点的个数。
6469

6570
<!-- tabs:start -->
6671

6772
```python
6873
class Solution:
6974
def countPaths(self, n: int, roads: List[List[int]]) -> int:
70-
INF = inf
71-
MOD = 10**9 + 7
72-
g = [[INF] * n for _ in range(n)]
75+
g = [[inf] * n for _ in range(n)]
7376
for u, v, t in roads:
74-
g[u][v] = t
75-
g[v][u] = t
77+
g[u][v] = g[v][u] = t
7678
g[0][0] = 0
77-
dist = [INF] * n
78-
w = [0] * n
79+
dist = [inf] * n
7980
dist[0] = 0
80-
w[0] = 1
81+
f = [0] * n
82+
f[0] = 1
8183
vis = [False] * n
8284
for _ in range(n):
8385
t = -1
84-
for i in range(n):
85-
if not vis[i] and (t == -1 or dist[i] < dist[t]):
86-
t = i
86+
for j in range(n):
87+
if not vis[j] and (t == -1 or dist[j] < dist[t]):
88+
t = j
8789
vis[t] = True
88-
for i in range(n):
89-
if i == t:
90+
for j in range(n):
91+
if j == t:
9092
continue
91-
ne = dist[t] + g[t][i]
92-
if dist[i] > ne:
93-
dist[i] = ne
94-
w[i] = w[t]
95-
elif dist[i] == ne:
96-
w[i] += w[t]
97-
return w[-1] % MOD
93+
ne = dist[t] + g[t][j]
94+
if dist[j] > ne:
95+
dist[j] = ne
96+
f[j] = f[t]
97+
elif dist[j] == ne:
98+
f[j] += f[t]
99+
mod = 10**9 + 7
100+
return f[-1] % mod
98101
```
99102

100103
```java
101104
class Solution {
102-
private static final long INF = Long.MAX_VALUE / 2;
103-
private static final int MOD = (int) 1e9 + 7;
104-
105105
public int countPaths(int n, int[][] roads) {
106+
final long inf = Long.MAX_VALUE / 2;
107+
final int mod = (int) 1e9 + 7;
106108
long[][] g = new long[n][n];
107-
long[] dist = new long[n];
108-
long[] w = new long[n];
109-
boolean[] vis = new boolean[n];
110-
for (int i = 0; i < n; ++i) {
111-
Arrays.fill(g[i], INF);
112-
Arrays.fill(dist, INF);
109+
for (var e : g) {
110+
Arrays.fill(e, inf);
113111
}
114-
for (int[] r : roads) {
112+
for (var r : roads) {
115113
int u = r[0], v = r[1], t = r[2];
116114
g[u][v] = t;
117115
g[v][u] = t;
118116
}
119117
g[0][0] = 0;
118+
long[] dist = new long[n];
119+
Arrays.fill(dist, inf);
120120
dist[0] = 0;
121-
w[0] = 1;
121+
long[] f = new long[n];
122+
f[0] = 1;
123+
boolean[] vis = new boolean[n];
122124
for (int i = 0; i < n; ++i) {
123125
int t = -1;
124126
for (int j = 0; j < n; ++j) {
@@ -134,85 +136,102 @@ class Solution {
134136
long ne = dist[t] + g[t][j];
135137
if (dist[j] > ne) {
136138
dist[j] = ne;
137-
w[j] = w[t];
139+
f[j] = f[t];
138140
} else if (dist[j] == ne) {
139-
w[j] = (w[j] + w[t]) % MOD;
141+
f[j] = (f[j] + f[t]) % mod;
140142
}
141143
}
142144
}
143-
return (int) w[n - 1];
145+
return (int) f[n - 1];
144146
}
145147
}
146148
```
147149

148150
```cpp
149-
typedef long long ll;
150-
151151
class Solution {
152152
public:
153-
const ll INF = LLONG_MAX / 2;
154-
const int MOD = 1e9 + 7;
155-
156153
int countPaths(int n, vector<vector<int>>& roads) {
157-
vector<vector<ll>> g(n, vector<ll>(n, INF));
158-
vector<ll> dist(n, INF);
159-
vector<ll> w(n);
160-
vector<bool> vis(n);
154+
const long long inf = LLONG_MAX / 2;
155+
const int mod = 1e9 + 7;
156+
157+
vector<vector<long long>> g(n, vector<long long>(n, inf));
158+
for (auto& e : g) {
159+
fill(e.begin(), e.end(), inf);
160+
}
161+
161162
for (auto& r : roads) {
162163
int u = r[0], v = r[1], t = r[2];
163164
g[u][v] = t;
164165
g[v][u] = t;
165166
}
167+
166168
g[0][0] = 0;
169+
170+
vector<long long> dist(n, inf);
171+
fill(dist.begin(), dist.end(), inf);
167172
dist[0] = 0;
168-
w[0] = 1;
173+
174+
vector<long long> f(n);
175+
f[0] = 1;
176+
177+
vector<bool> vis(n);
169178
for (int i = 0; i < n; ++i) {
170179
int t = -1;
171180
for (int j = 0; j < n; ++j) {
172-
if (!vis[j] && (t == -1 || dist[t] > dist[j])) t = j;
181+
if (!vis[j] && (t == -1 || dist[j] < dist[t])) {
182+
t = j;
183+
}
173184
}
174185
vis[t] = true;
175186
for (int j = 0; j < n; ++j) {
176-
if (t == j) continue;
177-
ll ne = dist[t] + g[t][j];
187+
if (j == t) {
188+
continue;
189+
}
190+
long long ne = dist[t] + g[t][j];
178191
if (dist[j] > ne) {
179192
dist[j] = ne;
180-
w[j] = w[t];
181-
} else if (dist[j] == ne)
182-
w[j] = (w[j] + w[t]) % MOD;
193+
f[j] = f[t];
194+
} else if (dist[j] == ne) {
195+
f[j] = (f[j] + f[t]) % mod;
196+
}
183197
}
184198
}
185-
return w[n - 1];
199+
return (int) f[n - 1];
186200
}
187201
};
188202
```
189203

190204
```go
191205
func countPaths(n int, roads [][]int) int {
192206
const inf = math.MaxInt64 / 2
193-
const mod = int(1e9) + 7
207+
const mod = int(1e9 + 7)
208+
194209
g := make([][]int, n)
195210
dist := make([]int, n)
196-
w := make([]int, n)
197-
vis := make([]bool, n)
198211
for i := range g {
199212
g[i] = make([]int, n)
200-
dist[i] = inf
201213
for j := range g[i] {
202214
g[i][j] = inf
215+
dist[i] = inf
203216
}
204217
}
218+
205219
for _, r := range roads {
206220
u, v, t := r[0], r[1], r[2]
207-
g[u][v], g[v][u] = t, t
221+
g[u][v] = t
222+
g[v][u] = t
208223
}
224+
225+
f := make([]int, n)
226+
vis := make([]bool, n)
227+
f[0] = 1
209228
g[0][0] = 0
210229
dist[0] = 0
211-
w[0] = 1
230+
212231
for i := 0; i < n; i++ {
213232
t := -1
214233
for j := 0; j < n; j++ {
215-
if !vis[j] && (t == -1 || dist[t] > dist[j]) {
234+
if !vis[j] && (t == -1 || dist[j] < dist[t]) {
216235
t = j
217236
}
218237
}
@@ -224,13 +243,55 @@ func countPaths(n int, roads [][]int) int {
224243
ne := dist[t] + g[t][j]
225244
if dist[j] > ne {
226245
dist[j] = ne
227-
w[j] = w[t]
246+
f[j] = f[t]
228247
} else if dist[j] == ne {
229-
w[j] = (w[j] + w[t]) % mod
248+
f[j] = (f[j] + f[t]) % mod
230249
}
231250
}
232251
}
233-
return w[n-1]
252+
return f[n-1]
253+
}
254+
```
255+
256+
```ts
257+
function countPaths(n: number, roads: number[][]): number {
258+
const mod: number = 1e9 + 7;
259+
const g: number[][] = Array.from({ length: n }, () => Array(n).fill(Infinity));
260+
for (const [u, v, t] of roads) {
261+
g[u][v] = t;
262+
g[v][u] = t;
263+
}
264+
g[0][0] = 0;
265+
266+
const dist: number[] = Array(n).fill(Infinity);
267+
dist[0] = 0;
268+
269+
const f: number[] = Array(n).fill(0);
270+
f[0] = 1;
271+
272+
const vis: boolean[] = Array(n).fill(false);
273+
for (let i = 0; i < n; ++i) {
274+
let t: number = -1;
275+
for (let j = 0; j < n; ++j) {
276+
if (!vis[j] && (t === -1 || dist[j] < dist[t])) {
277+
t = j;
278+
}
279+
}
280+
vis[t] = true;
281+
for (let j = 0; j < n; ++j) {
282+
if (j === t) {
283+
continue;
284+
}
285+
const ne: number = dist[t] + g[t][j];
286+
if (dist[j] > ne) {
287+
dist[j] = ne;
288+
f[j] = f[t];
289+
} else if (dist[j] === ne) {
290+
f[j] = (f[j] + f[t]) % mod;
291+
}
292+
}
293+
}
294+
return f[n - 1];
234295
}
235296
```
236297

0 commit comments

Comments
 (0)