• 算法笔记:图论单源最短路


    求解所有两点间的最短路的问题叫做任意任意两点间的最短路问题。

    Floyed-Warshall算法

    类似dp思想的一种最短路算法

    时间复杂度

    \(O(n^{3})\)

    处理限制

    • 可以处理边权为负的情况

    • 可以判断图中是否有负圈

    • 时间复杂度过高

    代码

    LuoGu P3371 【模板】单源最短路径

    //#define fre yes
    
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int maxn = 256+10;
    int d[maxn][maxn];
    
    int n,m,t;
    
    template<typename T>inline void read(T&x)
    {
        x = 0;char c;int lenp = 1;
        do { c = getchar();if(c == '-') lenp = -1; } while(!isdigit(c));
        do { x = x * 10 + c - '0';c = getchar(); } while(isdigit(c));
        x *= lenp;
    }
    
    void floyd(int x)
    {
        for (int k=1;k<=x;k++)
        {
            for (int i=1;i<=x;i++)
            {
                for (int j=1;j<=x;j++)
                {
                    d[i][j] = min(d[i][j],d[i][k]+d[k][j]);
                } } }
    }
    
    int main()
    {
        memset(d,0x3f3f3f3f,sizeof(d));
        read(n);read(m);read(t);
        for (int i=1;i<=m;i++)
        {
            int x,y,z;
            read(x);read(y);read(z);
            d[x][y] = z;
        } floyd(n);
        for (int i=1;i<=n;i++) { if(t == i) { printf("0 ");continue; }printf("%d ",d[t][i]); }
        return 0;
    }
    

    ####Shortest Path Faster Algorithm (Spfa)算法 最短路径最快的算法(开玩笑)

    类似广度优先搜索

    时间复杂度

    \(O(VE)\)

    V:顶点数
    E:边数

    处理限制

    • 可以处理边权为负的情况

    • 可以判断图中是否有负圈

    • 时间复杂度低,但容易被卡

    代码

    LuoGu P3371 【模板】单源最短路径

    //#define fre yes
    
    #include <queue>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int maxn = 256+10;
    int head[maxn];
    int edge[maxn];
    int ver[maxn];
    int to[maxn];
    
    int inq[maxn];
    int d[maxn];
    
    int n,m,t,tot;
    
    template<typename T>inline void read(T&x)
    {
        x = 0;char c;int lenp = 1;
        do { c = getchar();if(c == '-') lenp = -1; } while(!isdigit(c));
        do { x = x * 10 + c - '0';c = getchar(); } while(isdigit(c));
        x *= lenp;
    }
    
    void addedge(int x,int y,int z)
    {
        edge[tot] = z;
        ver[tot] = y;
        to[tot] = head[x];
        head[x] = tot++;
    }
    
    void spfa(int x)
    {
        queue<int> q;
    
        q.push(x);
        d[x] = 0; inq[x] = 1;
        while(!q.empty())
        {
            int now = q.front();q.pop();
            for (int i=head[now];~i;i=to[i])
            {
                int v = ver[i];
                if(d[v] > d[now] + edge[i])
                {
                    d[v] = d[now] + edge[i];
                    if(inq[v] == 1) continue;
                    inq[v] = 1;
                    q.push(v); 
                }
            }
        }
    }
    
    int main()
    {
        memset(d,0x3f3f3f3f,sizeof(d));
        memset(head,-1,sizeof(head));
    
        read(n);read(m);read(t);
        for (int i=1;i<=m;i++)
        {
            int x,y,z;
            read(x);read(y);read(z);
            addedge(x,y,z);
        } spfa(t);
    
        for (int i=1;i<=n;i++) printf("%d ",d[i]);
        return 0;
    }
    

    ####Dijkstra单源最短路算法

    类似广度优先搜索

    时间复杂度

    如果Spfa是\(O(V^{2})\)
    那么Dij就是\(O(Vlog_{E})\)

    处理限制

    • 不能处理负权的情况

    • 速度比Spfa要快点

    • 考试一般不卡

    代码

    LuoGu P3371 【模板】单源最短路径

    //#define fre yes
    
    #include <queue>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int maxn = 256+10;
    int head[maxn];
    int edge[maxn];
    int ver[maxn];
    int to[maxn];
    
    int d[maxn];
    
    int n,m,t,tot;
    
    template<typename T>inline void read(T&x)
    {
        x = 0;char c;int lenp = 1;
        do { c = getchar();if(c == '-') lenp = -1; } while(!isdigit(c));
        do { x = x * 10 + c - '0';c = getchar(); } while(isdigit(c));
        x *= lenp;
    }
    
    void addedge(int x,int y,int z)
    {
        edge[tot] = z;
        ver[tot] = y;
        to[tot] = head[x];
        head[x] = tot++;
    }
    
    void Dijkstra(int x)
    {
        priority_queue<pair<int,int> > q;
    
        d[x] = 0;
        q.push(make_pair(-d[x],x));
        while(!q.empty())
        {
            int now = q.top().second;q.pop();
            for (int i=head[now];~i;i=to[i])
            {
                int v = ver[i];
                if(d[v] > d[now] + edge[i])
                {
                    d[v] = d[now] + edge[i];
                    q.push(make_pair(-d[v],v)); 
                }
            }
        }
    }
    
    int main()
    {
        memset(d,0x3f3f3f3f,sizeof(d));
        memset(head,-1,sizeof(head));
    
        read(n);read(m);read(t);
        for (int i=1;i<=m;i++)
        {
            int x,y,z;
            read(x);read(y);read(z);
            addedge(x,y,z);
        } Dijkstra(t);
    
        for (int i=1;i<=n;i++) printf("%d ",d[i]);
        return 0;
    }
    
  • 相关阅读:
    228. Summary Ranges
    227. Basic Calculator II
    224. Basic Calculator
    222. Count Complete Tree Nodes
    223. Rectangle Area
    221. Maximal Square
    220. Contains Duplicate III
    219. Contains Duplicate II
    217. Contains Duplicate
    Java编程思想 4th 第4章 控制执行流程
  • 原文地址:https://www.cnblogs.com/Steinway/p/9211704.html
Copyright © 2020-2023  润新知