• [算法学习]floyd-warshall求多源最短路


    Floyd-warshall求解最短路的思路:

    通过第1~n每个顶点试图对任意一对顶点间距离进行“松弛”

    所谓松弛 就是指通过某个顶点使其他顶点对间距离缩短

    floyd的核心代码也正是这么干的emm

        for(int k = 1; k <= n; k++)
            for(int i = 1; i <= n; i++)
                for(int j = 1; j <= n; j++)
                    if(mp[i][j] > mp[i][k] + mp[k][j])
                        mp[i][j] = mp[i][k] + mp[k][j];

    非常简单粗暴的O(N^3)的时间复杂度(因为需要通过顶点直接访问边,邻接矩阵存图较为合适)

    而且emmm 因为N^3的时间复杂度,也不用担心数组开不了这么大的问题了。。开不了的 它也一定跑不过去

    然后…

    因为用邻接矩阵存图,就有一个平行边的问题=-=

    在最短路问题里,解决方法当然是……

        while(m--){
            int a, b, c;
            a = read(); b = read(); c = read();
            
            mp[a][b] = min(mp[a][b], c);
        }

    存短的边啦!

    然后floyd相比bellman-ford/dijkstra虽然复杂度比较高,但是可以求出任意两点的最短路径,均摊到每个点对上而言

    还是算不错的时间复杂度

    然后稍微贴道题吧…w

    洛谷P1629 邮递员送信https://www.luogu.com.cn/problem/P1629

    题目大意:邮递员从结点1往2~n号结点送包裹,每送完一件需要返回邮局,求邮递员完成邮递的最短路径

    边均为有向边且题目保证图连通(n<=10^3)

    (qwq一开始以为是无向图,直接dijkstra 然后把距离一加 *2 然后样例都过不去。。)

    由于是有向图,需要求出结点1到其他点的最短路与其他点到结点1的最短路

    然后数据不算大,可以考虑floyd+卡常ac 

    (这里正解比较巧(其实是我菜orz),同时正向建边和反向建边跑两次dijkstra即可)

    贴个ac代码:

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1e3 + 5, inf = 0x3f3f3f3f;
    int mp[maxn][maxn];
    
    int n, m;
    inline int read(){
        int x = 0,f = 1;
        char ch = getchar();
        
        while(!isdigit(ch)){if(ch == '-') f=-1; ch = getchar();}
        while(isdigit(ch)){x=x*10 + ch - '0'; ch = getchar();}
        return x*f;
    }
    
    int ans;
    
    int main(){
        n = read(); m = read();
    
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
                if(i != j)
                    mp[i][j] = inf;
                else mp[i][j] = 0;
    
        while(m--){
            int a, b, c;
            a = read(); b = read(); c = read();
            
            mp[a][b] = min(mp[a][b], c);
        }
    
        for(int k = 1; k <= n; k++)
            for(ri int i = 1; i <= n; i++)
                for(ri int j = 1; j <= n; j++)
                    if(mp[i][j] > mp[i][k] + mp[k][j])
                        mp[i][j] = mp[i][k] + mp[k][j];
    
        for(int i = 2; i <= n; i++)
            ans += mp[1][i] + mp[i][1];
        printf("%d", ans);
        return 0;
    }

    大概就是读入优化+O2优化可以过掉。。不开O2会T掉几个点emm 不过本来就不是正解了

    嗯=-= 如果数据不大的话,floyd还是很好的(Emm至少很好写)

  • 相关阅读:
    SQL Server SQLHelper帮助类
    Winform 常用的方法
    SQL Server 插入含有中文字符串出现乱码现象的解决办法
    ComboBox 中 DisplayMember 和 ValueMember 都是具体干什么的?
    HTML常用标签属性使用
    虚拟机安装windows server 2012 R2
    VS2017生成带图标的QT项目方法
    QSS 记录
    QT qss资源文件与代码分离
    pgsql 服务遇见的问题记录
  • 原文地址:https://www.cnblogs.com/leafsblogowo/p/12747967.html
Copyright © 2020-2023  润新知