[算法学习]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至少很好写)

原文地址:https://www.cnblogs.com/leafsblogowo/p/12747967.html