题解 | 【模板】单源最短路2

【模板】单源最短路2

https://www.nowcoder.com/practice/7c1740c3d4ba4b3486df4847ee6e8fc7

const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

class Node {
    constructor(id) {
        this.id = id;
        this.next = [];
        this.cost = Infinity;
        this.status = false;
    }
    addNext(next, cost) {
        this.next.push({ next, cost });
    }
}

void (async function () {
    const [maxNode, links] = (await readline()).split(" ").map(Number);
    const nodesMap = new Map();
    nodesMap.set(1, new Node(1));
    nodesMap.get(1).cost = 0;

    // 初始化优先队列,使用数组模拟最小堆
    const priorityQueue = [];
    priorityQueue.push([nodesMap.get(1), 0]);

    // 最小堆辅助函数
    function heapify(arr, index) {
        let left = 2 * index + 1;
        let right = 2 * index + 2;
        let smallest = index;

        if (left < arr.length && arr[left][1] < arr[smallest][1]) {
            smallest = left;
        }
        if (right < arr.length && arr[right][1] < arr[smallest][1]) {
            smallest = right;
        }
        if (smallest !== index) {
            [arr[index], arr[smallest]] = [arr[smallest], arr[index]];
            heapify(arr, smallest);
        }
    }

    function addToHeap(node, cost) {
        priorityQueue.push([node, cost]);
        let i = priorityQueue.length - 1;
        while (i > 0 && priorityQueue[Math.floor((i - 1) / 2)][1] > priorityQueue[i][1]) {
            [priorityQueue[i], priorityQueue[Math.floor((i - 1) / 2)]] = [priorityQueue[Math.floor((i - 1) / 2)], priorityQueue[i]];
            i = Math.floor((i - 1) / 2);
        }
    }

    for (let i = 1; i <= links; i++) {
        const [start, end, cost] = (await readline()).split(" ").map(Number);
        if (!nodesMap.has(start)) {
            nodesMap.set(start, new Node(start));
        }
        if (!nodesMap.has(end)) {
            nodesMap.set(end, new Node(end));
        }
        nodesMap.get(start).addNext(end, cost);
        nodesMap.get(end).addNext(start, cost);
    }

    while (priorityQueue.length > 0) {
        // 取出堆顶元素
        let minElement = priorityQueue[0];
        priorityQueue[0] = priorityQueue[priorityQueue.length - 1];
        priorityQueue.pop();
        heapify(priorityQueue, 0);

        const [u, currentCost] = minElement;

        if (u.status) continue;
        u.status = true;

        for (const { next: v, cost: edgeCost } of u.next) {
            if (nodesMap.get(v).cost > currentCost + edgeCost) {
                nodesMap.get(v).cost = currentCost + edgeCost;
                addToHeap(nodesMap.get(v), nodesMap.get(v).cost);
            }
        }
    }

    rl.close();
    console.log(nodesMap.get(maxNode)?.cost === Infinity ? -1 : nodesMap.get(maxNode)?.cost || -1);
})();

思路其实都大差不差,主要是代码方面的时间优化,还有一些边界情况的考虑。

Dijkstra算法,核心就是用一个优先队列来存储后续需要进行对比的任务,然后方便拿取数据用一个node class来存储数据及状态。

全部评论

相关推荐

不愿透露姓名的神秘牛友
07-10 11:27
明天又是董事长面,啥时候是个头啊
在太阳里长大的人:公司就仨人吧😂
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务