zoukankan      html  css  js  c++  java
  • 最短路

    最短路

    • 1.单源最短路
      • 所有边权都是正的
        • 朴素Dijkstra O( n^2 )
        • 堆优化Dijkstra O(mlogn)
        • 存在负权边
          • Bellman-Ford O(mn)
          • SPFA 一般O(m),最坏O(mn)
    • 2.多源汇最短路 Floyd算法 O(n^3)

    朴素Dijkstra

    • 1.初始化距离,dis[1]=0,dis[i]=INF;
    • 2.遍历集合,找到不在s(当前已确定最短距离的点)中的距离最近的点,更新当前其他点的距离;
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int N = 510;
    
    int m, n;
    int g[N][N], dist[N];
    bool st[N];
    
    int dijkstra() {
        memset(dist, 0x3f, sizeof dist);
        dist[1] = 0;
        for (int i = 0; i < n; ++i) {
            int t = -1;
            for (int j = 1; j <= n; ++j) {
                if (!st[j] && (t == -1 || dist[t] > dist[j])) t = j;
            }
            st[t] = true;
    
            for (int j = 1; j <= n; ++j) {
                dist[j] = min(dist[j], dist[t] + g[t][j]);
            }
        } 
        if (dist[n] == 0x3f3f3f3f) return -1;
        return dist[n];
    }
    
    
    int main() {
        cin >> n >> m;
    
        memset(g, 0x3f, sizeof g);
        
        while (m--) {
            int a, b, c;
            cin >> a >> b >> c;
            g[a][b] = min(g[a][b], c);
        }
        cout << dijkstra() << endl;
        return 0;
    }
    

    堆优化Dijkstra

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    
    using namespace std;
    
    typedef pair<int, int> PII;
    
    const int N = 100010;
    
    int n, m;
    int h[N], w[N], e[N], ne[N], idx;
    int dist[N];
    bool st[N];
    
    void add(int a, int b, int c) {
        e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
    }
    
    int dijkstra() {
        memset(dist, 0x3f, sizeof dist);
        dist[1] = 0;
        priority_queue<PII, vector<PII>, greater<PII>> heap;
        heap.push({0, 1});
        while (heap.size()) {
            auto t = heap.top();
            heap.pop();
            
            int ver = t.second, distance = t.first;
            if (st[ver]) {
                continue;
            } 
            for (int i = h[ver]; i != -1; i = ne[i]) {
                int j = e[i];
                if (dist[j] > distance + w[i]) {
                    dist[j] = distance + w[i];
                    heap.push({dist[j], j});
                }
            }
        }
        if (dist[n] == 0x3f3f3f3f) return -1;
        return dist[n];
    }
    
    int main () {
        cin >> n >> m;
        memset(h, -1, sizeof h);
        
        while (m--) {
            int a, b, c;
            cin >> a >> b >> c;
            add(a, b, c);
        }
        
        cout << dijkstra() << endl;
        
        return 0;    
    }
    

    Bellman-Ford

    • n次迭代,循环所有边a、b、w,更新距离;

    • dist[b] <= dist[a] + w;
      
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    const int N = 510, M = 10010;
    int n, m, k;
    int dist[N], backup[N];
    
    struct {
        int a, b, w;
    } edges[M];
    
    int bellman_ford() {
        memset(dist, 0x3f, sizeof dist);
        dist[1] = 0;    
        for (int i = 0; i < k; ++i) {
            memcpy(backup, dist, sizeof dist);
            for (int j = 0; j < m; ++j) {
                int a = edges[j].a, b = edges[j].b, w = edges[j].w;
                dist[b] = min(dist[b],backup[a] + w);
            }
        }
        if (dist[n] > 0x3f3f3f3f / 2) return -1;
        return dist[n];
    }
    
    int main() {
        cin >> n >> m >> k;
        
        for (int i = 0; i < m; ++i) {
            int a, b, c;
            cin >> a >> b >> c;
            edges[i] = {a, b, c};
        }
        int t = bellman_ford();
        if (t == -1) printf("impossible
    ");
        else printf("%d
    ", t);
        return 0;
    }
    

    SPFA

    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <cstring>
    const int N = 100010;
    using namespace std;
    int n, m, h[N], e[N], ne[N], w[N], dist[N], idx;
    bool st[N];
    
    
    void add(int a, int b, int c) {
        e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++; 
    }
    
    int spfa() {
        memset(dist, 0x3f, sizeof dist);
        dist[1] = 0;
        
        queue<int> q;
        q.push(1);
        st[1] = true;
        
        while (q.size()) {
            int t = q.front();
            q.pop();
            st[t] = false;
            
            for (int i = h[t]; i != -1; i = ne[i]) {
                int j = e[i];
                if (dist[j] > dist[t] + w[i]) {
                    dist[j] = dist[t] + w[i];
                    if (!st[j]) {
                        q.push(j);
                        st[j] = true;
                    }
                }
            }
        }
        if(dist[n] == 0x3f3f3f3f) return -1;
        return dist[n];
    }
    
    int main() {
        cin >> n >> m;
        memset(h, -1, sizeof h);
        
        while (m--) {
            int a, b, c;
            cin >> a >> b >> c;
            add(a, b, c);
        }
        int t = spfa();
        if (t == -1) puts("impossible");
        else cout << t << endl;
        return 0;
    }
    

    Floyd

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    
    const int N = 210, INF = 1e9;
    int n, m, q;
    int d[N][N];
    
    void floyd() {
        for (int k = 1; k <= n; ++k) {
            for (int i = 1; i <= n ;++i) {
                for (int j = 1; j <= n; ++j) {
                    d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
                }
            }
        }
    }
    
    int main() {
        cin >> n >> m >> q;
        for (int i = 1; i <= n ; ++i) {
            for (int j = 1; j <= n; ++j) {
                if (i == j) d[i][j] = 0;
                else d[i][j] = INF;
            }
        }
        
        while (m--) {
            int a, b, w;
            cin >> a >> b >> w;
            d[a][b] = min(d[a][b], w);
        }
        floyd();
        
        while (q--) {
            int a, b;
            cin >> a >> b;
            if (d[a][b] > INF / 2) printf("impossible
    ");
            else printf("%d
    ", d[a][b]);
        }
        
        return 0;
    }
    



  • 相关阅读:
    【视频开发】【电子电路技术】监控球机PTZ的功能介绍
    【电子电路技术】PoE供电技术的优缺点
    【电子电路技术】PoE供电技术的优缺点
    【python开发】利用PIP3的时候出现的问题Fatal error in launcher: Unable to create process using '"'
    【python开发】利用PIP3的时候出现的问题Fatal error in launcher: Unable to create process using '"'
    【Python开发】C和Python之间的接口实现
    Nginx配置域名转发实例
    Nginx配置域名跳转实例
    MySQL查看数据库大小、表大小和最后修改时间
    iptables阻止服务器被攻击
  • 原文地址:https://www.cnblogs.com/clown9804/p/12521329.html
Copyright © 2011-2022 走看看