一.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

最短路的几种算法及其优化(模板)相关推荐

  1. MySQL ALGORITHM = UNDEFINED/MERGE/TEMPORTARY 详解视图的三种算法与优化方案

    CREATE [ALGORITHM = {MERGE | TEMPTABLE | UNDEFINED}] VIEW [database_name].[view_name] AS [SELECT sta ...

  2. 最近公共祖先三种算法详解 + 模板题 建议新手收藏 例题: 信息学奥赛一本通 祖孙询问 距离

    首先什么是最近公共祖先?? 如图:红色节点的祖先为红色的1, 2, 3. 绿色节点的祖先为绿色的1, 2, 3, 4. 他们的最近公共祖先即他们最先相交的地方,如在上图中黄色的点就是他们的最近公共祖先 ...

  3. 最短路小结(三种算法+各种常见变种)

    额,博主只是做了几(约数)道题而已,写这篇小结纯粹想留作纪念(勿喷,但是可以交流)(那啥,转载的话注明一下来源..打字不容易..) 最短路呢,包括三种算法,但是各有各的变种,其中变化有很多. 简单记录 ...

  4. 【十大排序算法】(一)冒泡排序算法(优化)

    一.优化第一版 优化第一版是针对类似 int[] arr = {3,2,1,4,5,6,7,8,9; 这样的有很多已经排好序的数组,为了不让它做无用的循环,对于此场景进行的优化,优化代码如下: // ...

  5. 最短路算法(3种算法)

    1.最短路 最短路,顾名思义,最短的路径.我们把边带有权值的图称为带权图.边的权值可以理解为两点之间的距离.一张图中任意两点之间会有不同的路径相连.最短路径就是指连接两点的这些路径中最短的一条.我们有 ...

  6. 多目标优化算法:MOFPA、MOFA、MOCS、MOBA、MOHHO五种多目标优化算法性能对比(提供MATLAB源码)

    多目标花朵授粉算法(MOFPA) 多目标萤火虫算法(MOFA) 多目标布谷鸟搜索算法(MOCS) 多目标蝙蝠优化算法(MOBA) 多目标哈里斯鹰优化算法(MOHHO) 参考文献: 将MOFPA.MOF ...

  7. 两种动态灰狼优化算法

    文章目录 一.理论基础 1.灰狼优化算法 2.第一种动态灰狼优化算法(DGWO1) 3.第二种动态灰狼优化算法(DGWO2) 二.仿真实验与分析 三.参考文献 一.理论基础 1.灰狼优化算法 请参考这 ...

  8. 一种增强型鲸鱼优化算法

    文章目录 一.理论基础 1.基本鲸鱼优化算法 2.改进鲸鱼优化算法 (1)非线性时变的自适应权重 (2)差分变异微扰因子 (3)改进的螺旋更新方式 (4)EWOA算法的流程图 二.实验分析 三.参考文 ...

  9. 榛子树搜索算法(Hazelnut tree search algorithm,HTS)——一种高效的优化算法

    榛子树搜索算法(Hazelnut tree search algorithm,HTS)--一种高效的优化算法 榛子树搜索算法(Hazelnut tree search algorithm,HTS)是一 ...

最新文章

  1. schema.sql自动写入。由于版本问题。2.x之后。就不行了。·
  2. Quality Certificate Check at Goods Receipt
  3. mysql创建表的时候,字段尽量不要为NULL
  4. 太阳能计算机屏幕是什么材质,魅蓝E的屏幕怎么样?屏幕材质是什么?
  5. cdgb调试linux崩溃程序
  6. c# winform TreeView与ListView的项互相拖动的应用[转载]
  7. 基于OpenCL的数字地形分析之坡度坡向提取
  8. 基于EasyDSS流媒体服务器实现的直播流管理与鉴权的后台方案
  9. 马斯克又一语双关 引用猫王金曲威胁直接向推特股东发要约收购?
  10. 深度学习笔记——生成模型
  11. VC6.0的工程设置解读Project--Settings
  12. 如何关闭苹果Mac上的触控板功能防止误触?
  13. distpicker省市区插件设置请选择省市区提示/或设置初始值问题
  14. 有哪些比较好的国外知名广告联盟平台?
  15. 分享一个在线Word编辑的jQuery插件
  16. 跨越专业翻译的语言之墙:百度翻译的技术攀登
  17. 《圣经》中最让人感动的十句话(转)
  18. CMock使用手册翻译
  19. java登陆拦截器_登陆拦截器LoginInterceptor
  20. 《基础微积分教材中译版》--11.3偏导数

热门文章

  1. 安卓系统dicom阅读器_用户分享:电子书阅读器Note Pro,一座贴心的移动图书馆...
  2. java 插入mysql 日期_Java日期-插入数据库
  3. vba 当前文件名_VBA代码解决方案第77讲内容:如何导出文件
  4. 菜鸟学java要多久_菜鸟学java,根本停不下来!
  5. 模拟视频光端机与数字光端机究竟有何区别
  6. HDMI光端机是什么?hdmi光端机产品参数及性能特点介绍
  7. 什么是节点光端机?总线型光端机有哪些优势?
  8. 21秋期末考试工商企业文化10631k2
  9. [渝粤教育] 中国地质大学 事故应急救援 复习题
  10. 【渝粤题库】陕西师范大学152212 政府绩效管理 作业(专升本)