1976. 到达目的地的方案数 O(m log m)、O(m)【Dijkstra 算法 + 优先队列 + 过程中DP】

63 阅读1分钟

1976. 到达目的地的方案数

Dijkstra 算法 : 若有 包含负权重的边的 环, 失效

class Solution:
    def countPaths(self, n: int, roads: List[List[int]]) -> int:
        # 邻接表
        # 优先队列:  路径时长, 点的编号  0 到 node 的路径最短时长  不断刷新
        e = [[] for _ in range(n)]  # 邻接表
        for u, v, t in roads:
            e[u].append((v, t))
            e[v].append((u, t))

        times = [0] + [inf] * (n - 1)  # 0 到 结点 i 的路径最短时长为 times[i]
        ways = [1] + [0] * (n - 1)  # 获得 0 到 结点 i 的最短时长路径 的方案数 为 ways[i]

        mod = 10**9 + 7
        q = [[0, 0]] # 路径时长 结点   根据路径时长 维护  小根树
        while q:
            cur, u = heappop(q) # 结点 u 即其 最短时长
            if cur > times[u]:
                continue 
            for v, t in e[u]:
                if cur + t < times[v]:
                    times[v] = cur + t 
                    ways[v] = ways[u]
                    heappush(q, [cur + t, v])
                elif cur + t == times[v]:
                    ways[v] = (ways[u] + ways[v]) % mod 
        
        return ways[-1]

image.png

class Solution {
public:
    int countPaths(int n, vector<vector<int>>& roads) {
        const long long mod = 1e9 + 7;
        vector<vector<pair<int, int>>> e(n);
        for (auto r : roads){
            int u = r[0], v = r[1], t = r[2];
            e[u].emplace_back(v, t);
            e[v].emplace_back(u, t);
        }
        vector<long long> dis(n, LLONG_MAX);
        vector<long long> ways(n);   // 0 到 结点 i 获得 最短路径 dis[i] 的方法数

        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> q; // 优先弹出 最小值
        q.emplace(0, 0); // 最短路径时长  结点
        dis[0] = 0;
        ways[0] = 1;

        while (!q.empty()){
            auto [t, u] = q.top(); q.pop();
            if (t > dis[u]){
                continue;
            }
            for (auto [v, w] : e[u]){
                if (t + w < dis[v]){
                    dis[v] = t + w;
                    ways[v] = ways[u];
                    q.emplace(t + w, v);
                }else if (t + w == dis[v]){
                    ways[v] = (ways[u] + ways[v]) % mod;
                }
            }
        }
        return ways[n - 1];
    }
};