题目地址:
https://leetcode.com/problems/number-of-ways-to-arrive-at-destination/
给定一个 n n n个顶点的无向带权图,顶点编号 0 , 1 , . . . , n − 1 0,1,...,n-1 0,1,...,n−1。求 0 0 0到 n − 1 n-1 n−1最短路的条数。
用Dijkstra算法,可以在Dijkstra树上按拓扑序做一下递推。思路参考https://blog.csdn.net/qq_46105170/article/details/121900779。代码如下:
import java.util.Arrays;
import java.util.PriorityQueue;
public class Solution {
class Pair {
long d;
int v;
public Pair(long d, int v) {
this.d = d;
this.v = v;
}
}
int[] h, e, ne, w;
int idx, MOD = (int) (1e9 + 7);
void add(int a, int b, int c) {
e[idx] = b;
ne[idx] = h[a];
w[idx] = c;
h[a] = idx++;
}
public int countPaths(int n, int[][] roads) {
int m = roads.length;
h = new int[n];
Arrays.fill(h, -1);
e = new int[m << 1];
ne = new int[m << 1];
w = new int[m << 1];
for (int[] road : roads) {
int a = road[0], b = road[1], c = road[2];
add(a, b, c);
add(b, a, c);
}
// 距离会爆int,要用long
long[] dist = new long[n];
int[] cnt = new int[n];
Arrays.fill(dist, Long.MAX_VALUE);
dist[0] = 0;
cnt[0] = 1;
boolean[] vis = new boolean[n];
PriorityQueue<Pair> heap = new PriorityQueue<>((x, y) -> Long.compare(x.d, y.d));
heap.offer(new Pair(0, 0));
while (!heap.isEmpty()) {
Pair cur = heap.poll();
int u = cur.v;
if (vis[u]) {
continue;
}
if (u == n - 1) {
break;
}
vis[u] = true;
for (int i = h[u]; i != -1; i = ne[i]) {
int v = e[i];
if (dist[v] > dist[u] + w[i]) {
dist[v] = dist[u] + w[i];
cnt[v] = cnt[u];
heap.offer(new Pair(dist[v], v));
} else if (dist[v] == dist[u] + w[i]) {
cnt[v] = (cnt[v] + cnt[u]) % MOD;
}
}
}
return cnt[n - 1];
}
}
时间复杂度 O ( m log n ) O(m\log n) O(mlogn)( m m m是图的边数),空间 O ( n ) O(n) O(n)。