JavaScript Djikstras + Memoization
javascript\nvar countRestrictedPaths = function(n, edges) {\n    // create an adjacency list to store the neighbors with weight for each node\n    const adjList
```javascript\nvar countRestrictedPaths = function(n, edges) {\n    // create an adjacency list to store the neighbors with weight for each node\n    const adjList = new Array(n + 1).fill(null).map(() => new Array(0));\n    for (const [node1, node2, weight] of edges) {\n        adjList[node1].push([node2, weight]);\n        adjList[node2].push([node1, weight]);\n    }\n    \n    // using djikstras algorithm\n    // find the shortest path from n to each node\n    const nodeToShortestPathDistance = {}\n    const heap = new Heap();\n    heap.push([n, 0])\n    let numNodeSeen = 0;\n    while (numNodeSeen < n) {\n        const [node, culmativeWeight] = heap.pop();\n        if (nodeToShortestPathDistance.hasOwnProperty(node)) {\n            continue;\n        }\n        nodeToShortestPathDistance[node] = culmativeWeight;\n        numNodeSeen++;\n        for (const [neighbor, edgeWeight] of adjList[node]) {\n            if (nodeToShortestPathDistance.hasOwnProperty(neighbor)) {\n                continue;\n            }\n            heap.push([neighbor, edgeWeight + culmativeWeight]);\n        }\n    }\n    \n\n    // do a DFS caching the number of paths for each node\n    // so that we don\'t need to redo the number of paths again\n    // when we visit that node through another path\n    const nodeToNumPaths = {};\n    const dfs = (node) => {\n        if (node === n) return 1;\n        if (nodeToNumPaths.hasOwnProperty(node)) {\n            return nodeToNumPaths[node];\n        }\n        let count = 0;\n        for (const [neighbor, weight] of adjList[node]) {\n            if (nodeToShortestPathDistance[node] > nodeToShortestPathDistance[neighbor]) {\n                count += dfs(neighbor);\n            }\n        }\n        return nodeToNumPaths[node] = count % 1000000007;\n    }\n    return dfs(1);\n};\n\nclass Heap {\n    constructor() {\n        this.store = [];\n    }\n    \n    peak() {\n        return this.store[0];\n    }\n    \n    size() {\n        return this.store.length;\n    }\n    \n    pop() {\n        if (this.store.length < 2) {\n            return this.store.pop();\n        }\n        const result = this.store[0];\n        this.store[0] = this.store.pop();\n        this.heapifyDown(0);\n        return result;\n    }\n    \n    push(val) {\n        this.store.push(val);\n        this.heapifyUp(this.store.length - 1);\n    }\n    \n    heapifyUp(child) {\n        while (child) {\n            const parent = Math.floor((child - 1) / 2);\n            if (this.shouldSwap(child, parent)) {\n                [this.store[child], this.store[parent]] = [this.store[parent], this.store[child]]\n                child = parent;\n            } else {\n                return child;\n            }\n        }\n    }\n    \n    heapifyDown(parent) {\n        while (true) {\n            let [child, child2] = [1,2].map((x) => parent * 2 + x).filter((x) => x < this.size());\n            if (this.shouldSwap(child2, child)) {\n                child = child2\n            }\n            if (this.shouldSwap(child, parent)) {\n                [this.store[child], this.store[parent]] = [this.store[parent], this.store[child]]\n                parent = child;\n            } else {\n                return parent;\n            }\n        }\n    }\n    \n    shouldSwap(child, parent) {\n        return child && this.store[child][1] < this.store[parent][1];\n    }\n}\n```
['Dynamic Programming', 'JavaScript']