当前位置:首页 > 力扣 > 力扣3112题解法:带时间限制的最短路径问题解析(C++代码)

力扣3112题解法:带时间限制的最短路径问题解析(C++代码)

3个月前 (06-25)

力扣3112题解法:带时间限制的最短路径问题解析(C++代码) 力扣 图论算法 Dijkstra算法 优先队列 C++ 第1张

一、题目解读

力扣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. 明确标记不可达节点,符合题目输出要求。

该思路适用于有时间限制的最短路径问题,对算法优化与逻辑严谨性有较高要求,为同类题目提供通用解法模板。


原创内容 转载请注明出处

分享给朋友:

相关文章

力扣746:三步通关最小花费爬楼梯

力扣746:三步通关最小花费爬楼梯

题目解析:站在楼梯的某个台阶时,需要支付当前台阶对应的体力值cost[i],之后可以选择向上爬1或2个台阶。最终目标是到达‌楼层顶部‌(即数组末尾之后的位置),且初始位置可选择下标0或1的台阶作为起点...

力扣35:二分法在搜索插入位置中的运用

力扣35:二分法在搜索插入位置中的运用

有序数组的定位在一个严格递增的数字序列中,每个元素都有其确定的位置。当新元素试图加入时,我们需要回答两个问题:它是否已经存在?如果不存在,它应该插入在哪里?这道题要求我们在O(log n)时间内完成这...

力扣1137题:动态规划解泰波那契数 高效求解第N项的秘密

力扣1137题:动态规划解泰波那契数 高效求解第N项的秘密

一:重新解读题目泰波那契数列是一个充满数学趣味的递推序列:从第3项开始,每个数均为前三个数的和(即Tₙ₊₃ = Tₙ + Tₙ₊₁ + Tₙ₊₂)。当给定整数n时,需要高效计算出第n项的值。面对此类递...

力扣540题:线性扫描法如何高效定位唯一数

力扣540题:线性扫描法如何高效定位唯一数

题目重解一个严格递增的有序数组中,除某个元素外,其余每个元素均出现两次。这个看似简单的条件背后隐藏着巧妙的规律——单一元素会打破数组的"成对对称性"。题目要求以O(log n)时间...

手搓顺序表类代码注释与详解:从零实现动态数组(新手教程)

一、简介和特点顺序表(Sequential List)是数据结构中基础的一种线性表,其特点是将数据元素存储在连续的内存空间中。通过数组实现,支持随机访问(即通过索引直接访问元素),适用于频繁随机读取的...

力扣第44题:寻找两个正序数组的中位数 - 合并排序解法详解

力扣第44题:寻找两个正序数组的中位数 - 合并排序解法详解

内容简介本文详细解析了力扣第44题"寻找两个正序数组的中位数"的合并排序解法。通过双指针技术合并两个有序数组,然后直接计算合并后数组的中位数。虽然时间复杂度为O(m+n),但这种方...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。