最短路的几种算法及其优化(模板)
一.Dijkstra 算法
dijkstra算法适用于边权为正的情况,求单源最短路,适用于有向图和无向图
模板伪代码:
清除所有点的标号
设d[0]=0,其余d[i]=INF;
循环n次{
在所有未标记的节点中,寻找d[i]最小的点x
给x做标记
对于从x出发的所有边(x,y)更新d[y]=min(d[y],d[x]+w[x,y]);
}
memset(v,0,sizeof(v)); for(int i=0;i<n;++i) d[i]=(i==0?0:INF); for(int i=0;i<n;++i) {int x,m=INF;for(int j=0;j<n;++j)if(!visit[j]&&d[j]<m){m=d[j];x=j;}visit[x]=1;for(int j=0;j<n;++j)d[j]=min(d[j],d[x]+w[x][j]);}
简单说一下dijkstra的优化:
1.储存结构上:邻接矩阵是很占空间的(众所周知),所以我们一般采用邻接表或者边表
2.堆优化:因为在dijkstra中有循环n次寻找最小dict的过程,我们可以维护一个小根堆来实现,也就把时间复杂度从n^2降到了n*(logn+E)。
优化后的dijkstra,自己写的:
/* 建图用的邻接表,复杂度O(E*logE) */struct pnode {int num;int len;pnode() {}pnode(int a, int b) : num(a), len(b) {}//初始化结构体用的,把a复制给num,把b复制给len; bool operator < (const pnode tmp) const {return len > tmp.len;} };int dis[N]; bool vis[N]; int n;void dijkstra(int s) {priority_queue<pnode> q;q.push(pnode(s, 0));pnode u;int v, i, res = inf;for(i = 0; i <= n; ++i) dis[i] = inf, vis[i] = false;dis[s] = 0;while(!q.empty()) {u = q.top(); q.pop();if(u.len != dis[u.num]) continue;/*这是应对优先队列中的重复入队的点,只要最新的那个点就可以了*/if(vis[u.num]) continue;vis[u.num] = true;for(i = head[u.num]; i != -1; i = g[i].next) {v = g[i].to;if(dis[v] > u.len + g[i].val) {dis[v] = u.len + g[i].val;q.push(pnode(v, dis[v]));}}} }
二.Bellman-Ford的优化(也就是SPFA,直接看三吧)
三.SPFA模板及SPFA的优化
1.普通SPFA模板(队列化的Bellman-Ford算法):
int visit[N],dis[N]; bool SPFA(int s) {queue<int>q;memset(dis,127,sizeof(dis));memset(visit,false,sizeof(visit)); memset(cnt,0s,sizeof(cnt));dis[s]=0;visit[s]=true;q.push(s);while(!q.empty()){int k=q.front();q.pop();visit[k]=false;for(int i=head[k];i;i=edge[i].last)/*边表*/{if(dis[k]+edge[i].w<dis[edge[i].v]){dis[edge[i].v]=dis[k]+edge[i].w;if(!visit[edge[i].v]){q.push(edge[i].v);visit[edge[i].v]=true; if(++cnt[edge[i].v]>n) /*如果某一个点的入队次数超过了n次,说明存在负环,返回false*/ return false;}}}}return true;/*安全跑完了,不存在环*/ }
2.SPFA的优化
SPFA算法有两个优化策略SLF和LLL——SLF:Small Label First 策略,设要加入的节点是j,队首元素为i,若dist(j)<dist(i),则将j插入队首,否则插入队尾; LLL:Large Label Last 策略,设队首元素为i,队列中所有dist值的平均值为x,若dist(i)>x则将i插入到队尾,查找下一元素,直到找到某一i使得dist(i)<=x,则将i出队进行松弛操作。 SLF 可使速度提高 15 ~ 20%;SLF + LLL 可提高约 50%。 在实际的应用中SPFA的算法时间效率不是很稳定,为了避免最坏情况的出现,通常使用效率更加稳定的Dijkstra算法。实际上dijkstra算法+heap优化后是一定快于一般SPFA的,而且更加稳定。
1)SPFA的SLF优化,(很简单的,只要使用双端队列就可以实现了)。
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <deque> using namespace std; const int N=501; const int NN=100001; const int inf=0x7fffffff; int n,nu; typedef struct node {int adj,val;struct node *next; }; node node[NN],*p[N]; int SPFA() {deque<int> qu;int x,i,a,b;int vis[N],dis[N],num[N];struct node *head[N];for(i=1;i<=n;i++){vis[i]=0;num[i]=0;dis[i]=inf;head[i]=p[i];}dis[1]=0;vis[1]=1;num[1]++;qu.push_back(1);while(!qu.empty()){x=qu.front();qu.pop_front();vis[x]=0;head[x]=p[x];while(head[x]){a=head[x]->adj;b=head[x]->val;if(dis[a]>dis[x]+b){dis[a]=dis[x]+b;if(!vis[a]){vis[a]=1;num[a]++;if(num[a]>=n)return 1;if(!qu.empty()){if(dis[a]>dis[qu.front()])qu.push_back(a);elsequ.push_front(a);}elsequ.push_back(a);}}head[x]=head[x]->next;}}return 0; } int main() {int t,i,m,w,a,b,c;scanf("%d",&t);while(t--){memset(node,0,sizeof(node));memset(p,0,sizeof(p));nu=0;scanf("%d%d%d",&n,&m,&w);for(i=0;i<m;i++){scanf("%d%d%d",&a,&b,&c);node[nu].adj=b;node[nu].val=c;node[nu].next=p[a];p[a]=&node[nu];nu++;node[nu].adj=a;node[nu].val=c;node[nu].next=p[b];p[b]=&node[nu];nu++;}for(i=0;i<w;i++){scanf("%d%d%d",&a,&b,&c);node[nu].adj=b;node[nu].val=-c;node[nu].next=p[a];p[a]=&node[nu];nu++;}if(SPFA())puts("YES");elseputs("NO");}return 0; }
网上找的
#include<iostream> using namespace std; #include<deque> #include<cstdio> #include<cstring> int n,m; #define N 1001 struct Edge{int u,v,w,last; }edge[N]; int head[N]; int dict[N]; bool visit[N]; void input() {scanf("%d%d",&n,&m);/*n个点,m条边*/for(int i=1;i<=m;++i){scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);edge[i].last=head[edge[i].u];head[edge[i].u]=i;} } bool SPFA() {deque<int>q;memset(dict,127,sizeof(dict));memset(visit,false,sizeof(visit));dict[1]=0;visit[1]=true;;int cnt[N];memset(cnt,0,sizeof(cnt));/*判断有无环的标志*/++cnt[1];while(!q.empty()){int k=q.front();q.pop_front();visit[k]=false;/*取出后,不要忘记标志位*/for(int l=head[k];l;l=edge[l].last)/*边表*/{int p=edge[l].v;if(dict[p]>dict[k]+edge[l].w){dict[p]=dict[k]+edge[l].w;++cnt[p];if(cnt[p]>n) return true;/*如果某个点的入队次数超过了n,那么一定存在环*/if(!visit[p]){visit[p]=true;if(!q.empty())/*这就是SLF Small Label First 策略.的核心,把将要入队的元素的dict与队首元素相比较,如果将要入队的元素的dict大的话,就放在队尾,否则就放在队首 */{if(dict[p]>dict[q.front()])/*这样可以保证始终用dict小的更新,也节约了时间*/q.push_back(p);else q.push_front(p);/*所以必须使用双端队列*/}else q.push_back(p);/*不要忘记考虑队列为空的情况*/}}}}return false; } int main() {input();if(SPFA())printf("circle");else{for(int i=1;i<=n;++i)printf("%d ",dict[i]);}return 0; }
自己打了一遍,还可以理解
2.SPFA的LLL优化
在网上实在没找到可靠的。
3.SPFA的DFS优化:
在很多的题目中,SPFA都是用BFS来实现的,对于随机图来说,BFS的速度会远大于DFS,但是对于某些特殊的图结构来说,DFS也是一个很好的选择
例如 1):题目中要求在最短的时间内,判断有无环,DFS明显会比BFS快(例题是POj上一个判断单词接龙的题目)
2):对于网格型的图,DFS的速度比BFS快
模板:
void SPFA(int k) {flag[k]=true;for(int l=head[k];l;l=edge[l].last){int v=edge[l].v;/*找出第一个可以被更新的点*/if(dis[v]>dis[k]+edge[l].w){dis[v]=dis[k]+edge[l].w;if(!flag[v]){SPFA(v);/*接着深搜下去*/}else /*这表明从某个点开始DFS,结果又搜到了这个点,说明存在负权回路*/{printf("cycle");return;}}}flag[k]=false;/*不要忘记再把k设为false,为的是让他能够重复入队*/ }
四,Floyd算法模板(没有任何优化,就是邻接矩阵和n^3,一般情况单源最短路是绝对不会用的)
for(int k=1;k<=n;++k)/*注意这个k必须在最外层循环才行*/for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
转载于:https://www.cnblogs.com/c1299401227/p/5401240.html
最短路的几种算法及其优化(模板)相关推荐
- MySQL ALGORITHM = UNDEFINED/MERGE/TEMPORTARY 详解视图的三种算法与优化方案
CREATE [ALGORITHM = {MERGE | TEMPTABLE | UNDEFINED}] VIEW [database_name].[view_name] AS [SELECT sta ...
- 最近公共祖先三种算法详解 + 模板题 建议新手收藏 例题: 信息学奥赛一本通 祖孙询问 距离
首先什么是最近公共祖先?? 如图:红色节点的祖先为红色的1, 2, 3. 绿色节点的祖先为绿色的1, 2, 3, 4. 他们的最近公共祖先即他们最先相交的地方,如在上图中黄色的点就是他们的最近公共祖先 ...
- 最短路小结(三种算法+各种常见变种)
额,博主只是做了几(约数)道题而已,写这篇小结纯粹想留作纪念(勿喷,但是可以交流)(那啥,转载的话注明一下来源..打字不容易..) 最短路呢,包括三种算法,但是各有各的变种,其中变化有很多. 简单记录 ...
- 【十大排序算法】(一)冒泡排序算法(优化)
一.优化第一版 优化第一版是针对类似 int[] arr = {3,2,1,4,5,6,7,8,9; 这样的有很多已经排好序的数组,为了不让它做无用的循环,对于此场景进行的优化,优化代码如下: // ...
- 最短路算法(3种算法)
1.最短路 最短路,顾名思义,最短的路径.我们把边带有权值的图称为带权图.边的权值可以理解为两点之间的距离.一张图中任意两点之间会有不同的路径相连.最短路径就是指连接两点的这些路径中最短的一条.我们有 ...
- 多目标优化算法:MOFPA、MOFA、MOCS、MOBA、MOHHO五种多目标优化算法性能对比(提供MATLAB源码)
多目标花朵授粉算法(MOFPA) 多目标萤火虫算法(MOFA) 多目标布谷鸟搜索算法(MOCS) 多目标蝙蝠优化算法(MOBA) 多目标哈里斯鹰优化算法(MOHHO) 参考文献: 将MOFPA.MOF ...
- 两种动态灰狼优化算法
文章目录 一.理论基础 1.灰狼优化算法 2.第一种动态灰狼优化算法(DGWO1) 3.第二种动态灰狼优化算法(DGWO2) 二.仿真实验与分析 三.参考文献 一.理论基础 1.灰狼优化算法 请参考这 ...
- 一种增强型鲸鱼优化算法
文章目录 一.理论基础 1.基本鲸鱼优化算法 2.改进鲸鱼优化算法 (1)非线性时变的自适应权重 (2)差分变异微扰因子 (3)改进的螺旋更新方式 (4)EWOA算法的流程图 二.实验分析 三.参考文 ...
- 榛子树搜索算法(Hazelnut tree search algorithm,HTS)——一种高效的优化算法
榛子树搜索算法(Hazelnut tree search algorithm,HTS)--一种高效的优化算法 榛子树搜索算法(Hazelnut tree search algorithm,HTS)是一 ...
最新文章
- schema.sql自动写入。由于版本问题。2.x之后。就不行了。·
- Quality Certificate Check at Goods Receipt
- mysql创建表的时候,字段尽量不要为NULL
- 太阳能计算机屏幕是什么材质,魅蓝E的屏幕怎么样?屏幕材质是什么?
- cdgb调试linux崩溃程序
- c# winform TreeView与ListView的项互相拖动的应用[转载]
- 基于OpenCL的数字地形分析之坡度坡向提取
- 基于EasyDSS流媒体服务器实现的直播流管理与鉴权的后台方案
- 马斯克又一语双关 引用猫王金曲威胁直接向推特股东发要约收购?
- 深度学习笔记——生成模型
- VC6.0的工程设置解读Project--Settings
- 如何关闭苹果Mac上的触控板功能防止误触?
- distpicker省市区插件设置请选择省市区提示/或设置初始值问题
- 有哪些比较好的国外知名广告联盟平台?
- 分享一个在线Word编辑的jQuery插件
- 跨越专业翻译的语言之墙:百度翻译的技术攀登
- 《圣经》中最让人感动的十句话(转)
- CMock使用手册翻译
- java登陆拦截器_登陆拦截器LoginInterceptor
- 《基础微积分教材中译版》--11.3偏导数
热门文章
- 安卓系统dicom阅读器_用户分享:电子书阅读器Note Pro,一座贴心的移动图书馆...
- java 插入mysql 日期_Java日期-插入数据库
- vba 当前文件名_VBA代码解决方案第77讲内容:如何导出文件
- 菜鸟学java要多久_菜鸟学java,根本停不下来!
- 模拟视频光端机与数字光端机究竟有何区别
- HDMI光端机是什么?hdmi光端机产品参数及性能特点介绍
- 什么是节点光端机?总线型光端机有哪些优势?
- 21秋期末考试工商企业文化10631k2
- [渝粤教育] 中国地质大学 事故应急救援 复习题
- 【渝粤题库】陕西师范大学152212 政府绩效管理 作业(专升本)