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;
}
原文地址:https://www.cnblogs.com/hznumqf/p/12252403.html