最短路径问题
来源:互联网 发布:淘宝手办黑店 编辑:程序博客网 时间:2024/06/07 19:31
有关最短路径的算法主要有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,即:
for(i=1;i<=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算法:
尚未研究,等待最新更新。
- 最短路径问题
- 最短路径问题
- 最短路径问题
- 最短路径问题
- 最短路径问题
- 最短路径问题
- 最短路径问题
- 最短路径问题
- 最短路径问题
- 最短路径问题
- 最短路径问题
- 最短路径问题
- 最短路径问题
- 最短路径问题
- 最短路径问题
- 最短路径问题
- 最短路径问题
- 最短路径问题
- 【Android】悬浮按钮
- 安卓自定义View基础04-自定义view的分类以及常用方法讲解
- iOS Delegate通俗理解,使用详解,你还在仅仅拿来传值使吗?
- img标签读取本地图片
- J.U.C之并发工具类:CyclicBarrier
- 最短路径问题
- css 伪类:last-child等不起作用
- linux基本命令及操作15(ftp)
- Struts2官方教程:消息资源文件(Message Resource Files)
- netty学习六:第一个protobuf小demo
- LaTex常见编译问题
- 二分图最大匹配
- AL
- 位操作符-数字如何转化为二进制并进行操作