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

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

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

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


原创内容 转载请注明出处

分享给朋友:

相关文章

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

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

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

征服力扣704题:三步掌握经典二分查找算法

征服力扣704题:三步掌握经典二分查找算法

题目重解我们面对的是算法领域最经典的二分查找问题:在一个已排序的整数数组中,快速定位目标值的位置。就像在一本按字母顺序排列的字典中查找单词,我们不需要逐页翻阅,而是通过不断折半的方式快速缩小搜索范围,...

力扣第654题:最大二叉树解题教程 用数组构造最大二叉树

力扣第654题:最大二叉树解题教程 用数组构造最大二叉树

题目解读给定一个不含重复元素的整数数组,我们需要构建一棵最大二叉树。构建规则是:数组中的最大值作为根节点,其左侧子数组构建左子树,右侧子数组构建右子树,然后递归地应用这个规则。这种构建方式体现了分治思...

力扣965题深度解析:单值二叉树的判断技巧

力扣965题深度解析:单值二叉树的判断技巧

重新解读题目 判断一棵二叉树是否为“单值二叉树”,即所有节点的值是否完全相同。题目看似简单,实则考验对树结构递归特性的理解。若一棵树的所有节点值相同,其必然满足:根节点与左右子树的值一致,且...

标题:洛谷B3617题解析:八进制转十六进制算法实现与优化(附AC100代码)

标题:洛谷B3617题解析:八进制转十六进制算法实现与优化(附AC100代码)

一、题目解读洛谷B3617题要求将输入的八进制字符串转换为十六进制表示。题目需处理大数场景,且对输入合法性有明确限制(长度不超过1000,仅包含0-7字符)。由于八进制与十六进制无法直接转换,需借助十...

牛客14496题解:括号最大深度问题(栈思想与代码优化)

牛客14496题解:括号最大深度问题(栈思想与代码优化)

一、题目解读牛客14496题要求计算给定括号字符串中的最大深度。例如,对于字符串 "(()())",最大深度为2。题目考察对括号嵌套结构的理解,以及如何通过编程找到最深嵌套层次。二...

发表评论

访客

看不清,换一张

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