Description
You are in a city that consists of n
intersections numbered from 0
to n - 1
with bi-directional roads between some intersections. The inputs are generated such that you can reach any intersection from any other intersection and that there is at most one road between any two intersections.
You are given an integer n
and a 2D integer array roads
where roads[i] = [ui, vi, timei]
means that there is a road between intersections ui
and vi
that takes timei
minutes to travel. You want to know in how many ways you can travel from intersection 0
to intersection n - 1
in the shortest amount of time.
Return the number of ways you can arrive at your destination in the shortest amount of time. Since the answer may be large, return it modulo 109 + 7
.
Example 1:
Input: n = 7, roads = [[0,6,7],[0,1,2],[1,2,3],[1,3,3],[6,3,3],[3,5,1],[6,5,1],[2,5,1],[0,4,5],[4,6,2]] Output: 4 Explanation: The shortest amount of time it takes to go from intersection 0 to intersection 6 is 7 minutes. The four ways to get there in 7 minutes are:
- 0 ➝ 6
- 0 ➝ 4 ➝ 6
- 0 ➝ 1 ➝ 2 ➝ 5 ➝ 6
- 0 ➝ 1 ➝ 3 ➝ 5 ➝ 6
Example 2:
Input: n = 2, roads = 1,0,10 Output: 1 Explanation: There is only one way to go from intersection 0 to intersection 1, and it takes 10 minutes.
Constraints:
1 <= n <= 200
n - 1 <= roads.length <= n * (n - 1) / 2
roads[i].length == 3
0 <= ui, vi <= n - 1
1 <= timei <= 109
ui != vi
- There is at most one road connecting any two intersections.
- You can reach any intersection from any other intersection.
Solution
Dijkstra’s Algorithm 的正確性以及為何只適用 edge weight > 0 的 graph 可以參考:Correctness of Dijkstra_s Algorithm。
這題題幹敘述看完就知道是要我們用 Dijkstra’s Algorithm 來解。
要思考的點是當 path cost 相同時,ways 的更新方式:當發現有另外一條 path 其 cost 和原本相等,則 ways 相加。
Python
class Solution:
def countPaths(self, n: int, roads: List[List[int]]) -> int:
# build adjacency list
adj_list = [[] for _ in range(n)]
for u, v, time in roads:
adj_list[u].append([v, time])
adj_list[v].append([u, time])
# Dijkstra's Algorithm for shortest path on non-negative weight graph
min_heap = [[0, 0]] # time, node
dist = [float('inf')] * n
ways = [0] * n
ways[0] = 1
MOD = 10 ** 9 + 7
while min_heap:
time_taken, node = heappop(min_heap)
# Ignore outdated heap entries
if time_taken > dist[node]:
continue
for neighbor, time in adj_list[node]:
new_time = time_taken + time
if new_time < dist[neighbor]:
dist[neighbor] = time_taken + time
ways[neighbor] = ways[node] % MOD
heappush(min_heap, [new_time, neighbor])
elif new_time == dist[neighbor]:
ways[neighbor] += ways[node]
ways[neighbor] %= MOD;
return ways[n - 1]
C++
也可以考慮使用 multiset
,可以先 delete 再 insert 來達成 update 的目的。
priority_queue
typedef pair<long long, long long> pa;
class Solution {
public:
int countPaths(int n, vector<vector<int>>& roads) {
int MOD = 1e9 + 7;
vector<vector<pa>> adj(n);
// min heap
priority_queue<pa, vector<pa>, greater<>> pq;
for(auto road: roads) {
adj[road[0]].push_back({road[1], road[2]});
adj[road[1]].push_back({road[0], road[2]});
}
vector<long long> dist(n, LONG_MAX);
vector<long long> ways(n);
ways[0] = 1;
dist[0] = 0;
pq.push({0, 0}); // dist, src
while(!pq.empty()) {
auto [d, u] = pq.top(); pq.pop();
if(d > dist[u]) continue;
for(auto [v, time]: adj[u]) {
if(dist[v] > d + time) {
dist[v] = d + time;
pq.push({dist[v], v});
ways[v] = ways[u];
} else if(dist[v] == d + time) {
ways[v] = (ways[v] + ways[u]) % MOD;
}
}
}
return ways[n-1];
}
};
Multiset
typedef pair<long long, long long> pa;
class Solution {
public:
int countPaths(int n, vector<vector<int>>& roads) {
int MOD = 1e9 + 7;
vector<vector<pa>> adj(n);
multiset<pa> min_heap;
for(auto road: roads) {
adj[road[0]].push_back({road[1], road[2]});
adj[road[1]].push_back({road[0], road[2]});
}
vector<long long> dist(n, LONG_MAX);
vector<long long> ways(n);
ways[0] = 1;
dist[0] = 0;
min_heap.insert({0, 0}); // dist, src
while(!min_heap.empty()) {
auto [d, u] = *min_heap.begin();
min_heap.erase(min_heap.begin());
for(auto [v, time]: adj[u]) {
if(dist[v] > d + time) {
if(min_heap.find({dist[v], v}) != min_heap.end()) {
min_heap.erase(min_heap.find({dist[v], v}));
}
dist[v] = d + time;
min_heap.insert({dist[v], v});
ways[v] = ways[u];
} else if(dist[v] == d + time) {
ways[v] = (ways[v] + ways[u]) % MOD;
}
}
}
return ways[n-1];
}
};