最短路径问题

有关最短路径的算法主要有Floyd-Warshall,Dijsktra,Bellman-Ford,SPFA等算法,各有各的优点,这里做一个总结,总结一下这几天的思绪。
Floyd-Warshall算法:
简单暴力,通过不断松弛,找出两点之间的最短路径(遍历整个图,如果有e[i][j]>e[i][k]+e[k][j],就把e[i][j]更新为e[i][k]+e[k][j],可以通过三层循环暴力循环来解出来),缺点是不能处理负权边,时间复杂度为O(N^3).代码实现如下:

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

Dijsktra算法:
Dijsktra算法主要用来解决单源最短路径问题,就拿从1号顶点出发到节点n来说,先把各个点到源点1的路径长度存入数组dis,即:

fori=1i<=n;i++)
dis[i]=e[1][i];

存入之后把节点1用book数组标记一下,然后从小到大遍历dis数组,找出跟1相连的最小边,假设j节点离1最近,就从j节点开始找并把j节点标记一下,如果dis[j]+a[j][k]

for(i=1;i<=n;i++)
        dis[i]=a[1][i];
    book[1]=1;
    c=1;
    while(c<n)
    {
        min=inf;
        for(i=1;i<=n;i++)
        {
            if(book[i]==0&&min>dis[i])
            {
                min=dis[i];
                j=i;
            }
        }
        book[j]=1;
        c++;
        for(i=1;i<=n;i++)
        {
            if(dis[i]>dis[j]+a[j][i])
            {
                dis[i]=dis[j]+a[i][j];
            }
        }
    }

Bellman-Ford算法:
Bellman-Ford可以解决负权边的问题,源点到所有点最短路径问题。(最短路径肯定不包含回路,如果有正权回路,减去该回路所得值一定最小,如果是负权回路,那么就没有最小值)主要思想是“松弛”,跟Dijsktra很相似,所谓松弛就是如果2条边的和小于第三条边,就把第三条边的值赋为另两边的和,每一次都把所有的m条边遍历一遍,因为有n个顶点,所以有n-1条边,所以遍历n-1次。如果进行n-1次松弛之后,还能进行松弛,就说明路径中含有负权边。时间复杂度为O(NM).
代码实现如下:

for(i=1;i<=m;i++)
    {
        scanf("%d%d%d",&u[i],&v[i],&w[i]);
    }

    for(i=1;i<=n;i++)
    {
        dis[i]=inf;
    }
    dis[1]=0;
    for(k=1;k<=n-1;k++)
    {
        for(i=1;i<=m;i++)
        {
            if(dis[v[i]]>dis[u[i]]+w[i])
                {
                    printf("%d! ",dis[v[i]]);
                    dis[v[i]]=dis[u[i]]+w[i];

                    printf("%d# ",dis[v[i]]);
                }

        }
            printf("\n");
    }

    for(i=1;i<=n;i++)
    printf("%d ",dis[i]);
    printf("\n");

算法还能进行一些优化,如果在第n-1次松弛之前dis数组就不再进行变化,就直接跳出输出。(也就在每次松弛之前存储dis数组,松弛之后进行比对,如果有不一样的元素,就继续松弛,否则就跳出,这样可以优化算法的时间复杂度)
SPFA算法:
尚未研究,等待最新更新。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值