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


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

    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;
    }
    
  • 相关阅读:
    asp 向另一个页面传递数组
    TSQL Program Rule and Tips 规则与优化
    虚函数 纯虚函数 抽象类
    static (c#)
    简单游标
    抽象方法 抽象类 (abstract)
    清理电脑
    泛型学习
    继承(对象生命周期) + 覆盖[new](索引函数) + 重载[virtual/override]
    #干货向#jQuery性能优化指南
  • 原文地址:https://www.cnblogs.com/Steinway/p/9211704.html
Copyright © 2020-2023  润新知