相关概念:

有向图、无向图:有向图的边是双行道,无向图的边是单行道。在处理无向图时,可以把一条无向边看做方向相反的两条有向边。

圈 cycle / 回路 circuit:在相同顶点上开始并结束且长度大于0的通路。

环 loop:起点与终点重合的边。

负圈:含有负权边的圈。

  问题类型? 是否兼容负圈? 时间复杂度?
Bellman-Ford 单源 O(V·E)
Dijkstra 单源 × O(E·logV)
Floyd-Warshall 任意点对 O(V3)

1. Bellman-Ford 算法(单源) O(VE)

设d[]存放最短路径,对于每条边(from, to),d[to] = d[from] + cost 一定成立。

由于边在es[]中存储顺序的关系,可能出现计算到 d[to] 时 d[from] 还没出现的情况,此时d[to] 的值会继续保持INF,等到下一次循环再被更新。

当图中存在V个点时,从起点s出发共有V-1条路径,因此外层循环最多执行V-1次就能消除d[]中所有INF,并得到结果。如果图中存在负圈,最短路径会不断减小,外层循环执行次数就会超过V-1,因此只需检查更新次数是否达到V就能判断是否存在负圈。

 1 struct edge{int from,to,cost;};
2
3 edge es[MAX_E];
4 int d[MAX_V]; //shortest paths
5 int V,E; //number of vertices and edges
6
7 bool bellman_ford(int s)
8 {
9 for(int i=0;i<V;i++) //vertices are indexed from 0
10 d[i]=INF;
11 d[s]=0;
12 int n=0;
13 for(n=0;n<V;n++){ //to be executed |V|-1 times at most
14 bool update=false;
15 for(int i=0;i<E;i++){
16 edge e=es[i];
17 if(d[e.from]!=INF && d[e.to]>d[e.from]+e.cost){
18 d[e.to]=d[e.from]+e.cost;
19 update=true;
20 }
21 }
22 if(!update)
23 break;
24 if(n==V-1) //negative loops exists
25 return true;26 }
27 return false;
28 }

2.Dijkstra 算法(单源、无负圈)O(E·logV)

该算法的核心在于从已经确定最短路径的点出发,寻找相邻点的最短路径。

令d[s]=0,先更新s所有邻居的sp,入队,再从s所有邻居开始,更新它们的邻居的sp,以此类推……

借助升序优先队列,优先执行sp值小的点,可以避免内层for循环被不断执行,有效减小时间复杂度。

 1 struct edge{int to,cost;};
2 typedef pair<int,int> P; //first:sp second:termination
3
4 int V,E;
5 vector<edge> G[MAX_V]; //adjcent list
6 int d[MAX_V];
7
8 void dijkstra(int s)
9 {
10 priority_queue<P,vector<P>,greater<P>> que; //#include <queue>
11 fill(d,d+V+1,INF);
12 d[s]=0;
13 que.push(P(0,s));
14
15 while(!que.empty()){
16 P p=que.top(); que.pop();
17 int v=p.second;
18 if(d[v]<p.first) continue;
19 for(int i=0;i<G[v].size();i++){
20 edge e=G[v][i];
21 if(d[e.to]>d[v]+e.cost){
22 d[e.to]=d[v]+e.cost;
23 que.push(P(d[e.to],e.to)); //newly updated sp may change the sp of its neighbours
24 }
25 }
26 }
27 }

计算最短路径条数的方法:

维护数组 int cnt[MAX_V] 并初始化为 cnt[]=0; cnt[s]=1;

if ( d[e.to] > d[v]+e.cost )  cnt[e.to]=cnt[v]

else if ( d[e.to] == d[v]+e.cost )  cnt[e.to]+=cnt[v]

3.Floyd-Warshall 算法(任意点间) O(V3)

对于每个点对(i, j ) ,枚举中间点 k。i 到 j 的最短路径取经过中间点 k 和不经过中间点 k 两种情况的结果的最小值。

需要初始化:d[i][i]=0,不存在=INF

int d[MAX_V][MAX_V];  //weight of edges
int V,E; void floyd_warshall()
{
for(int k=0;k<V;k++)
for(int i=0;i<V;i++)
for(int j=0;j<V;j++)
d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
}

参考《挑战程序设计竞赛》(第二版),99-104;离散数学及其应用(中文第七版),595-612

最短路径(SP)问题相关算法与模板的更多相关文章

  1. 【2018寒假集训Day 7】【最短路径】三种算法的模板

    Luogu单源最短路径模版题 dijkstra #include<cstdio> #include<vector> using namespace std; const int ...

  2. [联赛可能考到]图论相关算法——COGS——联赛试题预测

    COGS图论相关算法 最小生成树 Kruskal+ufs int ufs(int x) { return f[x] == x ? x : f[x] = ufs(f[x]); } int Kruskal ...

  3. 盘点十大GIS相关算法

    1.道格拉斯-普克算法(Douglas–Peucker) 道格拉斯-普克算法(Douglas–Peucker algorithm,亦称为拉默-道格拉斯-普克算法.迭代适应点算法.分裂与合并算法)是将曲 ...

  4. 二叉树-你必须要懂!(二叉树相关算法实现-iOS)

    这几天详细了解了下二叉树的相关算法,原因是看了唐boy的一篇博客(你会翻转二叉树吗?),还有一篇关于百度的校园招聘面试经历,深刻体会到二叉树的重要性.于是乎,从网上收集并整理了一些关于二叉树的资料,及 ...

  5. 数据结构(C语言版)顺序栈相关算法的代码实现

    这两天完成了栈的顺序存储结构的相关算法,包括初始化.压栈.出栈.取栈顶元素.判断栈是否为空.返回栈长度.栈的遍历.清栈.销毁栈.这次的实现过程有两点收获,总结如下: 一.清楚遍历栈的概念 栈的遍历指的 ...

  6. 图论算法-Tarjan模板 【缩点;割顶;双连通分量】

    图论算法-Tarjan模板 [缩点:割顶:双连通分量] 为小伙伴们总结的Tarjan三大算法 Tarjan缩点(求强连通分量) int n; int low[100010],dfn[100010]; ...

  7. [java,2017-05-15] 内存回收 (流程、时间、对象、相关算法)

    内存回收的流程 java的垃圾回收分为三个区域新生代.老年代. 永久代 一个对象实例化时 先去看伊甸园有没有足够的空间:如果有 不进行垃圾回收 ,对象直接在伊甸园存储:如果伊甸园内存已满,会进行一次m ...

  8. 【STL学习】堆相关算法详解与C++编程实现(Heap)

    转自:https://blog.csdn.net/xiajun07061225/article/details/8553808 堆简介   堆并不是STL的组件,但是经常充当着底层实现结构.比如优先级 ...

  9. JS实现最短路径之弗洛伊德(Floyd)算法

    弗洛伊德算法是实现最小生成树的一个很精妙的算法,也是求所有顶点至所有顶点的最短路径问题的不二之选.时间复杂度为O(n3),n为顶点数. 精妙之处在于:一个二重初始化,加一个三重循环权值修正,完成了所有 ...

随机推荐

  1. lua tasklib 之lumen 分析

    sched.sleep分析 sleep会填充M.running_task.waitds数据表示当前task需要等待,最后yield出去到主线程 M.sleep = function (timeout) ...

  2. 洛谷P1605走迷宫

    传送 这是一道dfs,但是...但是....但是它竟然被放在bfs练习题辣!!!! 打了半天bfs,发现路径不会标记了,于是发现好像有什么不对的,似乎dfs要简单一点,于是半路跑去打dfs,结果打了半 ...

  3. Scrapy实战篇(五)之爬取历史天气数据

    本篇文章我们以抓取历史天气数据为例,简单说明数据抓取的两种方式: 1.一般简单或者较小量的数据需求,我们以requests(selenum)+beautiful的方式抓取数据 2.当我们需要的数据量较 ...

  4. 分布式CAP定理,为什么不能同时满足三个特性?

    在弄清楚这个问题之前,我们先了解一下什么是分布式的CAP定理. 根据百度百科的定义,CAP定理又称CAP原则,指的是在一个分布式系统中,Consistency(一致性). Availability(可 ...

  5. 04-模拟String去除空格trim()方法

    /** * 模拟String去除左右两边空格 * @param str */ public static String trim(String str) { char[] list = str.toC ...

  6. hessian的简单使用以及与spring整合

    Hessian是一个由Caucho Technology开发的轻量级二进制RPC协议.和其他Web服务的实现框架不同的是,Hessian是一个使用二进制格式传输的Web服务协议的框架,相对传统soap ...

  7. WebHttpRequest在sharepoint文档库中的使用

    写在前面 由于sharepoint服务器上的站点采用的域用户windows认证的方式登陆,而app项目虽然能够提供用户名和密码,但客户是不愿意在网络上这样传输的.所以给提供了使用ssl证书认证的方式. ...

  8. py库:文本转为语音(pywin32、pyttsx)

    http://blog.csdn.net/marksinoberg/article/details/52137547 Python 文本转语音 文本转为语音(使用Speech API) 需要安装 py ...

  9. 如何使用 Visual C# .NET 处理 Excel 事件

    事件处理概述 Visual C# .NET 使用委派处理来自组件对象模型 (COM) 服务器的事件.委派是 Microsoft Visual Studio .NET 中的一个新概念.对于 COM 事件 ...

  10. 转载:指针delete后要设置为NULL

    本文来自:http://rpy000.blog.163.com/blog/static/196109536201292615547939/ 众所周知,最开始我们用new来创建一个指针,那么等我们用完它 ...