Problem 3243 Shortest Distance After Road Addition Queries I
Table of Contents
Problem Statement
Link - Problem 3243
Question
You are given an integer n and a 2D integer array queries.
There are n cities numbered from 0 to n - 1. Initially, there is a unidirectional road from city i to city i + 1 for all 0 <= i < n - 1.
queries[i] = [ui, vi] represents the addition of a new unidirectional road from city ui to city vi. After each query, you need to find the length of the shortest path from city 0 to city n - 1.
Return an array answer where for each i in the range [0, queries.length - 1], answer[i] is the length of the shortest path from city 0 to city n - 1 after processing the first i + 1 queries.
Example 1:
Input: n = 5, queries = [[2,4],[0,2],[0,4]]
Output: [3,2,1]
Explanation:

After the addition of the road from 2 to 4, the length of the shortest path from 0 to 4 is 3.

After the addition of the road from 0 to 2, the length of the shortest path from 0 to 4 is 2.

After the addition of the road from 0 to 4, the length of the shortest path from 0 to 4 is 1.
Example 2:
Input: n = 4, queries = [[0,3],[0,2]]
Output: [1,1]
Explanation:

After the addition of the road from 0 to 3, the length of the shortest path from 0 to 3 is 1.

After the addition of the road from 0 to 2, the length of the shortest path remains 1.
Constraints:
3 <= n <= 5001 <= queries.length <= 500queries[i].length == 20 <= queries[i][0] < queries[i][1] < n1 < queries[i][1] - queries[i][0]- There are no repeated roads among the queries.
Solution
class Solution {
public:
vector<vector<int>> graph;
vector<int> distances;
int computeShortestPath(int start_node, int total_nodes) {
queue<int> bfs_queue;
bfs_queue.push(start_node);
while (!bfs_queue.empty()) {
int curr_node = bfs_queue.front();
bfs_queue.pop();
for (const int& neighbor : graph[curr_node]) {
if (distances[neighbor] > distances[curr_node] + 1) {
distances[neighbor] = distances[curr_node] + 1;
bfs_queue.push(neighbor);
}
}
}
return distances[total_nodes - 1];
}
vector<int> shortestDistanceAfterQueries(int total_nodes, vector<vector<int>>& queries) {
graph.resize(total_nodes);
for (int i = 0; i < total_nodes - 1; i++) {
graph[i].push_back(i + 1);
}
distances.resize(total_nodes);
iota(distances.begin(), distances.end(), 0);
// iota is used to prevent loops like this
// for (int i = 0; i < n; ++i) {
//distances[i] = i;
//}
vector<int> result;
result.reserve(queries.size());
for (const auto& query : queries) {
graph[query[0]].push_back(query[1]);
result.push_back(computeShortestPath(query[0], total_nodes));
}
return result;
}
};
Complexity Analysis
| Algorithm | Time Complexity | Space Complexity |
| ------------------------------ | --------------- | ---------------- |
| Unweighted Shortest Path (BFS) | O(nq) | O(n) |
Explanation
1. Intuition
- The problem can be solved using a graph and a breadth-first search (BFS) algorithm.
- We can represent the cities as nodes in the graph and the roads as directed edges.
- The shortest path from city 0 to city n-1 can be found by performing a BFS from city 0.
- We can use a queue to keep track of the nodes to visit next.
- We can use a distances array to keep track of the shortest distance from city 0 to each city.
- We can update the distances array as we visit each node.
- We can return the shortest distance from city 0 to city n-1 after each query.
2. Implementation
- We initialize the graph with n nodes and add a directed edge from each node to the next node.
- We initialize the distances array with the initial distances from city 0 to each city.
- We use the
iotafunction to initialize the distances array with the initial distances. - We iterate over the queries and add a directed edge from the start node to the end node.
- We call the
computeShortestPathfunction to update the distances array and return the shortest distance. - We use a queue to perform the BFS and update the distances array.
- We use the
push_backfunction to add nodes to the queue and thepopfunction to remove nodes from the queue. - We use the
resizefunction to resize the graph and distances array.
Complexity Analysis
Time Complexity:
- The time complexity is O(n*q) due to the nested loops in the
shortestDistanceAfterQueriesfunction. The outer loop iterates overqueries, which is of sizeq, and the inner loop contains thecomputeShortestPathfunction that performs BFS over thegraph. The BFS traversal has a time complexity of O(n) because it visits each node at most once. - The
computeShortestPathfunction has a time complexity of O(n) since it visits each node at most once. This is because thebfs_queueonly adds nodes that haven’t been visited yet, ensuring a linear traversal of the graph. - The
shortestDistanceAfterQueriesfunction also reserves memory for the result vector and initialises the graph, but these operations have a constant time complexity. Therefore, the overall time complexity is dominated by the nested loops.
Space Complexity:
- The space complexity is O(n) due to the storage required by the
graphanddistancesvectors. Thegraphis of sizen, where each element is another vector that has an average size ofn/total_nodes, but in the worst case, it can be as big asn. - The
distancesvector also requires O(n) space as it stores the shortest distance from each node to the destination. The result vector inshortestDistanceAfterQueriesrequires O(q) space but it’s not considered as part of the overall space complexity because it’s the output of the function. - The
bfs_queueused in thecomputeShortestPathfunction has a maximum size ofnin the worst case when the graph is fully connected. This contributes to the overall space complexity of O(n).
Footnote
This question is rated as Medium difficulty.
Hints
Maintain the graph and use an efficient shortest path algorithm after each update.
We use BFS/Dijkstra for each query.