There is an undirected weighted connected graph. You are given a positive integer n which denotes that the graph has n nodes labeled from 1 to n, and an array edges where each edges[i] = [ui, vi, weighti] denotes that there is an edge between nodes ui and vi with weight equal to weighti.
A path from node start to node end is a sequence of nodes [z0, z1, z2, ..., zk] such that z0 = start and zk = end and there is an edge between zi and zi+1 where 0 <= i <= k-1.
The distance of a path is the sum of the weights on the edges of the path. Let distanceToLastNode(x) denote the shortest distance of a path between node n and node x. A restricted path is a path that also satisfies that distanceToLastNode(zi) > distanceToLastNode(zi+1) where 0 <= i <= k-1.
Return the number of restricted paths from node1to noden. Since that number may be too large, return it modulo109 + 7.
Input:
n = 5, edges = [[1,2,3],[1,3,3],[2,3,1],[1,4,2],[5,2,2],[3,5,1],[5,4,10]]
Output:
3
Explanation: Each circle contains the node number in black and its `distanceToLastNode value in blue.` The three restricted paths are:
1) 1 --> 2 --> 5
2) 1 --> 2 --> 3 --> 5
3) 1 --> 3 --> 5
Example 2:
1
2
3
4
5
Input:
n = 7, edges = [[1,3,1],[4,1,2],[7,3,4],[2,5,3],[5,6,1],[6,7,2],[7,5,3],[2,6,4]]
Output:
1
Explanation: Each circle contains the node number in black and its `distanceToLastNode value in blue.` The only restricted path is 1 --> 3 --> 7.
The key idea is to use Dijkstra’s algorithm to compute the shortest distance from every node to node n. Then, use dynamic programming to count the number of restricted paths from node 1 to node n, where each step must go to a neighbor with a strictly smaller distance to node n.
classSolution {
publicintcountRestrictedPaths(int n, int[][] edges) {
finalint MOD = 1_000_000_007;
List<int[]>[] g =new List[n+1];
for (int i = 1; i <= n; i++) g[i]=new ArrayList<>();
for (int[] e : edges) {
g[e[0]].add(newint[]{e[1], e[2]});
g[e[1]].add(newint[]{e[0], e[2]});
}
int[] dist =newint[n+1];
Arrays.fill(dist, Integer.MAX_VALUE);
dist[n]= 0;
PriorityQueue<int[]> pq =new PriorityQueue<>(Comparator.comparingInt(a -> a[0]));
pq.offer(newint[]{0, n});
while (!pq.isEmpty()) {
int[] cur = pq.poll();
int d = cur[0], u = cur[1];
if (d > dist[u]) continue;
for (int[] vw : g[u]) {
int v = vw[0], w = vw[1];
if (dist[v]> d + w) {
dist[v]= d + w;
pq.offer(newint[]{dist[v], v});
}
}
}
Integer[] order =new Integer[n];
for (int i = 1; i <= n; i++) order[i-1]= i;
Arrays.sort(order, Comparator.comparingInt(a -> dist[a]));
int[] dp =newint[n+1];
dp[n]= 1;
for (int u : order) {
for (int[] vw : g[u]) {
int v = vw[0];
if (dist[u]> dist[v]) {
dp[u]= (dp[u]+ dp[v]) % MOD;
}
}
}
return dp[1];
}
}
classSolution {
funcountRestrictedPaths(n: Int, edges: Array<IntArray>): Int {
val MOD = 1_000_000_007
val g = Array(n+1) { mutableListOf<Pair<Int,Int>>() }
for (e in edges) {
g[e[0]].add(e[1] to e[2])
g[e[1]].add(e[0] to e[2])
}
val dist = IntArray(n+1) { Int.MAX_VALUE }
dist[n] = 0val pq = java.util.PriorityQueue(compareBy<Pair<Int,Int>> { it.first })
pq.add(0 to n)
while (pq.isNotEmpty()) {
val(d, u) = pq.remove()
if (d > dist[u]) continuefor ((v, w) in g[u]) {
if (dist[v] > d + w) {
dist[v] = d + w
pq.add(dist[v] to v)
}
}
}
val order = (1..n).sortedBy { dist[it] }
val dp = IntArray(n+1)
dp[n] = 1for (u in order) {
for ((v, _) in g[u]) {
if (dist[u] > dist[v]) {
dp[u] = (dp[u] + dp[v]) % MOD
}
}
}
return dp[1]
}
}
classSolution:
defcountRestrictedPaths(self, n: int, edges: list[list[int]]) -> int:
import heapq
MOD =10**9+7 g = [[] for _ in range(n+1)]
for u, v, w in edges:
g[u].append((v, w))
g[v].append((u, w))
dist = [float('inf')] * (n+1)
dist[n] =0 h = [(0, n)]
while h:
d, u = heapq.heappop(h)
if d > dist[u]: continuefor v, w in g[u]:
if dist[v] > d + w:
dist[v] = d + w
heapq.heappush(h, (dist[v], v))
order = sorted(range(1, n+1), key=lambda x: dist[x])
dp = [0] * (n+1)
dp[n] =1for u in order:
for v, _ in g[u]:
if dist[u] > dist[v]:
dp[u] = (dp[u] + dp[v]) % MOD
return dp[1]