最短路的各种算法

以下为各种最短路算法


Floyd

时间复杂度:O(n^3)

适用范围:求任意两点间的最短路,能够处理负边权,但无法处理负权回路。

主要思想:利用DP的思想,dis[i][j]=min(dis[i][k]+dis[k][j],dis[i][j]),不断更新至最优。

中心代码

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

练手题洛谷P2888洛谷P2910(题解洛谷上有)


Dijkstra

时间复杂度:O(n^2)

适用范围:单源最短路径(稳定性最高的算法),无法处理负边权。

主要思想:将图所有点的集合 S 分为两部分,V 和 S-V。V 集合是已经得到最短路径的点的集合,在初始情况下 V 中只有一个顶点 t,S-V 是还未得到最短路径点的集合。然后,在每一次迭代过程中取得 S-V 集中到 V 集合任一点距离最短的点,将其加到 V 集合,从 S-V 集合删除。重复此过程直到 S-V 集合为空。(非本人所写)

中心代码(邻接矩阵存图)

for (int i=1;i<=n;i++){ 
    ans=0x7fffffff;
    for (int j=1;j<=n;j++) 
        if ((f[j])&&(dist[j]<ans)) {
            ans=dist[j];
            st=j;
        }
    f[st]=false;
    for (int j=1;j<=n;j++) 
        if ((f[j])&&(dist[j]>dist[st]+g[st][j]))
            dist[j]=dist[st]+g[st][j];
}

练手题见SPFA


Bellman—Ford

时间复杂度:O(nm)

适用范围:单源最短路径,能够处理负边权,能够判断是否有负权回路。

主要思想:从起点出发,每次枚举已做过的点连接的所有边,修改未做过的点的距离,直到所有点都被更新。

中心代码

for (int i=1;i<n;i++)
    for (int j=1;j<=m;j++)
        if (dis[u]+w[j]<dis[v])
            dis[v]=dis[u]+w[j];

练手题见SPFA


SPFA

时间复杂度:O(km)(k为常数,平均值为2)

适用范围:同Bellman—Ford。

主要思想:同Bellman—Ford,用队列优化每次修改操作(其实叫做松弛操作)

中心代码

while(head<tail){
    int x=que[++head];
    exist[x]=false;
    for (int i=h[x];i;i=ed[i].next){
        dis[ed[i].to]=min(dis[ed[i].to],dis[x]+ed[i].dis);
        if (!exist[ed[i].to]){
            que[++tail]=ed[i].to;
            exist[ed[i].to]=true;
        }
    }
}

练手题HDUP2544HDUP1874HDUP2066(第一题和第三题题解博主有哦!第一题题解 第三题题解

就这样吧,有误还请多多指正!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值