Dijkstra算法,用优先队列的图遍历

注: 比较函数若使用c++中的引用语法[&dist](){...},优先队列中可不用存节点距离d。这里用各语言通用的写法。

int networkDelayTime(vector<vector<int>>& times, int N, int K) {
    // dijkstra算法
    unordered_map<int, unordered_map<int, int>> adj;
    for (auto &e : times) {
        adj[e[0]][e[1]] = e[2];
    }
    vector<int> dist(N + 1, INT_MAX); // 节点1..N
    dist[K] = 0;

    using arr2 = array<int, 2>; // [dist, node]
    auto cmp = [](arr2 &a, arr2 &b) { 
        return a[0] > b[0]; // 最小堆
    };
    priority_queue<arr2, vector<arr2>, decltype(cmp)> pq(cmp);
    pq.push({dist[K], K});

    while (!pq.empty()) {
        auto [d, u] = pq.top(); pq.pop();
        for (auto& [v, cost] : adj[u]) { // 遍历u的所有邻接点
            int newdist = d + cost;
            if (newdist < dist[v]) {
                dist[v] = newdist;
                pq.push({newdist, v});
            }
        }
    }

    int ans = INT_MIN;
    for (int i = 1; i <= N; i++) {
        ans = max(ans, dist[i]);
    }
    return (ans != INT_MAX) ? ans : -1;
}

Bellman-Ford算法

对所有边做V-1遍松弛(V个顶点的最短路径最多有V-1条边)。根据上一遍的距离值prev[]更新这一遍的距离值dist[]

  • https://leetcode.com/problems/network-delay-time/>]
int networkDelayTime(vector<vector<int>>& times, int N, int K) {
    // Bellman-Ford算法,对所有边做N-1次松弛
    const int INF = 1e7;
    vector<int> dist(N + 1, INF);
    dist[K] = 0;
    for (int i = 1; i < N; i++) {
        auto prev = dist;
        for (auto &e : times) {
            int u = e[0], v = e[1], cost = e[2];
            dist[v] = min(dist[v], prev[u] + cost);
        }
    }

    int ans = INT_MIN;
    for (int i = 1; i <= N; i++) {
        ans = max(ans, dist[i]);
    }
    return (ans != INF) ? ans : -1;
}
  • https://leetcode.com/problems/cheapest-flights-within-k-stops/
int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int K) {
    // 从src到dst最多K个中间站,共V=K+2个节点
    // Bellman-Ford算法,对所有边做V-1=K+1次松弛
    const int INF = 1e7;
    vector<int> dist(n, INF); // src到各节点的距离
    dist[src] = 0;
    for (int i = 0; i <= K; i++) {
        auto prev = dist;
        for (auto &e : flights) {
            int u = e[0], v = e[1], cost = e[2];
            dist[v] = min(dist[v], prev[u] + cost);
        }
    }
    return (dist[dst] != INF) ? dist[dst] : -1;
}

BFS

  • https://leetcode.com/problems/shortest-path-in-binary-matrix/
int shortestPathBinaryMatrix(vector<vector<int>>& grid) {
    // 从左上角到右下角的最短路径,bfs
    if (grid[0][0] == 1) return -1;
    const int R = grid.size(), C = grid[0].size();
    vector<vector<bool>> visited(R, vector<bool>(C, false));
    using arr3 = array<int, 3>; // [dist, i, j]
    queue<arr3> q;
    q.push({1, 0, 0});
    visited[0][0] = true;

    while (!q.empty()) {
        auto [d, r, c] = q.front();  q.pop();
        if (r == R - 1 && c == C - 1) return d;
        
        for (int dr = -1; dr <= 1; dr++) {
            for (int dc = -1; dc <= 1; dc++) {
                if (dr == 0 && dc == 0) continue;
                // 遍历8个方向
                int nr = r + dr, nc = c + dc;
                if (nr < 0 || nr >= R || nc < 0 || nc >= C 
                    || grid[nr][nc] || visited[nr][nc]) continue;
                q.push({d + 1, nr, nc});
                visited[nr][nc] = true;
            }
        }
    }
    return -1;
}