LeetCode--新增道路查询后的最短距离1
问题描述
给你一个整数 n 和一个二维整数数组 queries。 有 n 个城市,编号从 0 到 n - 1。初始时,每个城市 i 都有一条单向道路通往城市 i + 1( 0 <= i < n - 1)。 queries[i] = [ui, vi] 表示新建一条从城市 ui 到城市 vi 的单向道路。每次查询后,你需要找到从城市 0 到城市 n - 1 的最短路径的长度。 返回一个数组 answer,对于范围 [0, queries.length - 1] 中的每个 i,answer[i] 是处理完前 i + 1 个查询后,从城市 0 到城市 n - 1 的最短路径的长度。
有如下示例:
分析
面对此题,第一时间考虑的是广度优先搜索,一层一层遍历每一种可能的路径,考虑到每一条路径的权重都是1,最先达到终点的即为最短路径。 此外,考虑到最终的最短路径中,考虑到达终点的前一个节点,从起点到该节点的路径也必须是最短路径,据此可递推得到最终的最短路径,且考虑到在每一次添加数组queries中的边时,只有queries[i][1]及其之后的节点可能被影响,故在每次查询时,也只需重新计算从queries[i][1]之后的节点最短路径。
但是考虑到该题为最短路径问题,可以使用Dijkstra算法在每一次查询时计算最短路径。此解法并非最优,但这里用这种算法主要用于记录一种DIjkstra算法的C++的实现方式。
代码
#include <vector>
#include <queue>
#include <limits>
using namespace std;
struct Edge
{
int to;
int weight;
Edge() = delete;
Edge(int to, int weight): to(to), weight(weight){}
};
using Graph = vector<vector<Edge>>;
class Solution
{
private:
public:
vector<int> shortestDistanceAfterQueries(int n, vector<vector<int>>& queries)
{
Graph graph;
vector<int> answer;
int q_num = queries.size();
graph.resize(n);
for (int i = 0; i < n-1; i++)
{
graph[i].emplace_back(i+1, 1);
}
for (int i = 0; i < q_num; i++)
{
graph[queries[i][0]].emplace_back(queries[i][1], 1);
int ans = Dijkstra(graph, 0);
answer.emplace_back(ans);
}
return answer;
}
int Dijkstra(const Graph& graph, int start)
{
int n = graph.size();
vector<int> dist(n, __INT_MAX__);
dist[start] = 0;
// <distance, destination>
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq;
pq.emplace(0, start);
while (!pq.empty())
{
auto [curr_dist, curr_vertex] = pq.top();
pq.pop();
if(curr_dist > dist[curr_vertex]) continue;
for(const Edge& edge:graph[curr_vertex])
{
int new_dist = edge.weight + curr_dist;
if(new_dist < dist[edge.to])
{
dist[edge.to] = new_dist;
pq.emplace(new_dist, edge.to);
}
}
}
return dist.back();
}
};
这里记录图的结构体、选取最小距离时所用到的优先队列是之前不熟悉的用法,故记录在此。