zoukankan      html  css  js  c++  java
  • HZNUACM寒假集训Day4小结 最短路

      最短路

      1.Floy 复杂度O(N3  适用于任何图(不存在负环)

      模板 --kuangbin

       

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    
    const int INF = 0x3f3f3f3f;
    const int maxn = 1e3 + 50;
    
    int mp[maxn][maxn];
    int n, m;
    
    int main() {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j < m; j++) {
                if (i == j) mp[i][j] = 0;
                else mp[i][j] = INF;
            }
        }
        int u, v, w;
        for (int i = 1; i <= m; i++) {
            scanf("%d%d%d", &u, &v, &w);
            mp[u][v] = w;
        }
        for (int k = 1; k <= n; k++) {
            for (int i = 1; i <= n; i++) {
                for (int j = 1; j <= n; j++) {
                    mp[i][j] = min(mp[i][j], mp[i][k] + mp[k][j]);
                }
            }
        }
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                printf("%10d", mp[i][j]);
            }
            printf("\n");
        }
        return 0;
    }

       2.Dijkstra   适用于单源最短路 非负权图   堆优化 复杂度O((n+m)logm)

       

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<queue>
    using namespace std;
    
    const int INF = 0x3f3f3f3f;
    const int maxn = 1e3 + 50;
    
    struct Node {
        int v, c;   //c为到v点的最短路长度
        Node(int _v = 0,int _c=0): v(_v),c(_c) {}
        friend bool operator < (Node a, Node b) {
            return a.c > b.c;
        }
    };
    
    struct Edge {
        int v, cost;
        Edge(int _v = 0, int _cost = 0) : v(_v), cost(_cost) {}
    };
    
    vector<Edge> E[maxn];
    
    void add_edge(int u, int v, int w) {
        E[u].push_back(Edge(v, w));
    }
    
    int n, m;
    bool vis[maxn];
    bool dis[maxn];
    
    void Dijkstra(int n, int start) {
        memset(vis, 0, sizeof vis);
        for (int i = 1; i <= n; i++) dis[i] = INF;
        priority_queue<Node> q;
        while (!q.empty()) q.pop();
        dis[start] = 0;
        q.push(Node(start, 0));
        Node tmp;
        while (!q.empty()) {
            tmp = q.top();   q.pop();
            int u = tmp.v;
            if (vis[u]) continue;
            vis[u] = true;
            for (int i = 0; i < E[u].size(); i++) {
                int v = E[tmp.v][i].v;
                int cost = E[u][i].cost;
                if (!vis[v] && dis[v] > dis[u] + cost) {
                    dis[v] = dis[u] + cost;
                    q.push(Node(v, dis[v]));
                }
            }
        }
    }
    
    int main() {
        scanf("%d%d", &n, &m);
        int u, v, w;
        for (int i = 0; i < m; i++) {
            scanf("%d%d%d", &u, &v, &w);
            add_edge(u, v, w);
        }
        Dijkstra(n, 1);
        for (int i = 1; i <= n; i++) printf("%d ", dis[i]);
        return 0;
    }

         Bellman-Ford 算法  

        用于求解单源最短路问题的算法  可以肯定最短路径包含的边条数不会超过n-1个,或者说结点不超过n个 若超过说明形成一个环,又环权值是正的我们可以路径上将这个环删除路径长度就会变小

        可用于有向图判断是否存在负环

        总复杂度O(NM) 

        

    relax(u, v) {
        dist[v] = min(dist[v], dist[u] + edge_len(u, v));
    }
    for (i = 1; i <= n; i++) {
        dist[i] = edge_len(S, i);
    }
    for (i = 1; i < n; i++) {
        for each edge(u, v) {
            relax(u, v);
        }
    }

       Bellman-Ford 算法 优化  SPFA 最坏O(NM)

       存在负边权时用SPFA

       利用队列存储需要更新的结点,每次从队列中取出一个结点,计算是否有结点需要更新,如果有并且这个点不在队列里那么将它加入队列。

       

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<queue>
    using namespace std;
    
    const int INF = 0x3f3f3f3f;
    const int maxn = 1e3 + 50;
    
    struct Edge {
        int v, cost;
        Edge(int _v,int _cost): v(_v),cost(_cost) {}
    };
    
    vector<Edge> E[maxn];
    
    void add_edge(int u, int v, int w) {
        E[u].push_back(Edge(v, w));
    }
    
    bool vis[maxn];
    int cnt[maxn];
    int dis[maxn];
    
    bool spfa(int n, int start) {
        memset(vis, 0, sizeof vis);
        for (int i = 1; i <= n; i++)  dis[i] = INF;
        vis[start] = true;
        dis[start] = 0;
        queue<int> q;
        while (!q.empty()) q.pop();
        q.push(start);
        memset(cnt, 0, sizeof cnt);
        cnt[start] = 1;
        while (!q.empty()) {
            int u = q.front();
            q.pop();
            vis[u] = true;
            for (int i = 0; i < E[u].size(); i++) {
                int v = E[u][i].v;
                if (dis[v] > dis[u] + E[u][i].cost) {
                    dis[v] = dis[u] + E[u][i].cost;
                    if (!vis[v]) {
                        vis[v] = true;
                        q.push(v);
                        if (++cnt[v]> n) return false;
                    }
                }
            }
        }
        return true;
    }
  • 相关阅读:
    计算机考研复试真题 数字求和
    计算机考研复试真题 简单计算器
    计算机考研复试真题 N阶楼梯上楼问题
    P1082 [NOIP2012 提高组] 同余方程
    进制转换
    浮点数加法
    N的阶乘
    1055 The World's Richest (25 分)
    1028 List Sorting (25 分)
    1062 Talent and Virtue (25 分)
  • 原文地址:https://www.cnblogs.com/hznumqf/p/12252403.html
Copyright © 2011-2022 走看看