力扣3112题解法:带时间限制的最短路径问题解析(C++代码)
一、题目解读
力扣3112题要求解决带时间限制的最短路径问题:给定一个有向图,节点具有消失时间,需计算从起点到各节点的最短路径,且路径总时间不能超过节点的消失时间。题目难点在于需在传统最短路径算法(如Dijkstra)中融入时间窗口判断,确保到达节点时未“消失”。此外,需处理无法到达的节点并标记为-1。
二、解题思路
1. 核心思想:采用Dijkstra算法框架,结合时间限制优化。通过优先队列维护“当前时间+节点”的最小堆,确保每次扩展最短路径的节点。
2. 关键步骤:
构建邻接表存储带权边(节点+时间)。
初始化距离数组,起点为0,其余INT_MAX。
遍历邻接边时,判断新时间是否满足“未超时且更优”,更新距离并入队。
3. 优化点:
跳过已超时节点(time > dist[u]),减少无效计算。
无法到达节点标记为-1,避免INT_MAX误导。
三、解题步骤
1. 构建图结构:使用vector<pair<int, int>>构建邻接表,存储双向边(u→v, t时间)。
2. 初始化:距离数组dist初始化为INT_MAX,起点dist[0]=0;优先队列pq加入(0, 0)。
3. 主循环:
弹出堆顶(time, u),若time已超时(>dist[u]),跳过。
遍历u的邻接节点(v, t):计算新时间new_time = time + t。
若new_time < disappear[v](未超时)且更优,更新dist[v]并入队。
4. 后处理:将dist中仍为INT_MAX的节点置为-1,标记不可达。
四、代码及注释
class Solution { public: vector<int> minimumTime(int n, vector<vector<int>>& edges, vector<int>& disappear) { // 构建邻接表 vector<vector<pair<int, int>>> graph(n); for (const auto& edge : edges) { int u = edge[0], v = edge[1], t = edge[2]; graph[u].emplace_back(v, t); // 双向边 graph[v].emplace_back(u, t); } // 初始化距离数组 vector<int> dist(n, INT_MAX); dist[0] = 0; // 最小堆,存储(到达时间, 节点) priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq; pq.emplace(0, 0); while (!pq.empty()) { auto [time, u] = pq.top(); pq.pop(); // 跳过超时节点 if (time > dist[u]) continue; // 遍历邻接节点 for (const auto& [v, t] : graph[u]) { int new_time = time + t; // 检查时间限制并更新 if (new_time < disappear[v] && new_time < dist[v]) { dist[v] = new_time; pq.emplace(new_time, v); } } } // 处理无法到达的节点 for (int i = 0; i < n; ++i) { if (dist[i] == INT_MAX) { dist[i] = -1; } } return dist; } };
注释说明:
● 邻接表双向存储节省时间复杂度。
● 优先队列按时间排序,确保扩展顺序正确。
● 超时判断避免无效路径扩散,提升效率。
● 最终标记不可达节点满足题目要求。
五、总结
本文解法通过融合Dijkstra算法与严格的时间窗口判断,高效解决了力扣3112题。关键点在于:
1. 优先队列维护时间顺序,避免超时节点污染结果。
2. 邻接表双向存储适应无向图特性,降低代码复杂度。
3. 明确标记不可达节点,符合题目输出要求。
该思路适用于有时间限制的最短路径问题,对算法优化与逻辑严谨性有较高要求,为同类题目提供通用解法模板。
原创内容 转载请注明出处