目录

  • 简单介绍Bellman-Ford算法
    • 他的优点
    • 他的缺点
  • Dijstra算法思想
  • 优点与缺点
    • 他的缺点
    • 他的优点
  • 优化
    • 插入(更新)
    • 取出
  • 最后感想

简单介绍Bellman-Ford算法

定义:
d [ i ] : = 从 s 到 i 的 最 短 距 离 d[i]:=从s到i的最短距离 d[i]:=从s到i的最短距离
初始化:
d [ s ] = 0 , d [ i ] = I N F , i ∈ V d[s]=0,d[i]=INF,i \in V d[s]=0,d[i]=INF,i∈V
利用递推式:
d [ i ] = m i n { d [ j ] + ( 从 j 到 i 的 权 重 ) ∣ e = ( i , j ) ∈ E } d[i]=min\{ d[j]+(从j到i的权重)|e=(i,j)\in E \} d[i]=min{d[j]+(从j到i的权重)∣e=(i,j)∈E}
直到不在更新就完成了

代码:

#include<bits/stdc++.h>using namespace std;
const int MAX_V=100,MAX_E=100;
const int INF=0x7ffffff;
struct edge{int from,to,cost;
};
edge es[MAX_E];
int d[MAX_V];
int V,E;
void shortest_path(int s){for(int i=0;i<V;++i) d[i]=INF;d[s]=0;while(true){bool update=false;for(int i=0;i<E;++i){edge e= es[i];if(d[e.from]!=INF&&d[e.to]>d[e.from]+e.cost){d[e.to]=d[e.from]+e.cost;update=true;}}if(!update) break;}
}int main(){int s;cin>>V>>E;for(int i=0;i<E::++i){int s,e,w;cin>>s>>e>>w;es[i].from=s;es[i].to=e;es[i].cost=w;}cin>>s;shortest_path(s);for(int i=0;i<V;++i){printf("%d->%d的最短路:%d\n",s,i,d[i]);}return 0;
}

他的优点

对于负圈而言,Bellman-Ford算法能处理负圈。

因为负圈也就是有负权,那么自然对于每次循环自然可以更新,所以就会无限更新。但是我们稍微想一想,如果对于一个没有负圈的图中,我们最坏情况是要更新多少次呢?当然,可以想到是|V|-1次,因为如果存在一个节点i,从s到i必须经过所有节点,所以自然要迭代|V|-1才能更新这个i节点。
所以利用这个性质,我们可以实现检测是否存在负圈。
代码:

bool find_negative_loop(){memset(d,0,sizeof d);for(int i=0;i<V;++i){for(int j=0;j<E;++j){edge e=es[j];if(d[e.to]>d[e.from]+e.cost){d[e.to]=d[e.from]+e.cost;//如果第n次还有更新,则存在负圈if(i==V-1) return true;}}}return false;
}

他的缺点

每一次更新都需要将所有边遍历一遍,很浪费时间

正如上面代码所看,对于每次迭代,我们必须把所以边都遍历一次,对于可能仅仅需要更新一个边而言,实在是浪费。所以Dijstra算法就可以优化这个问题所以接着看吧。

Dijstra算法思想

根据Bellman-Ford算法的缺点,我们就可以思考:如何可以更高效的更新节点?
其实我们用人的思想可以看得出,如果对于 d [ i ] : = d[i]:= d[i]:=从s到i的最短路已经求出了后,那么对于节点 i i i附近的节点,可以推出附近节点的暂时的最短距离。而对于这个已经算出的 d [ i ] d[i] d[i]就可以不管了。
所以可以对上述概况为两点:

  1. 找到最短距离已经确定的顶点,从它出发更新相邻顶点的最短距离。
  2. 此后不需要再关心(1)中的“最短距离已经确定的点”。

那么怎么找这个“最短距离已经确定的点”?
最开始只有 d [ s ] = 0 d[s]=0 d[s]=0是已经确定的。而在尚未使用过的顶点中,距离 s s s节点最近的顶点就是最短路距离已经确定的顶点。如果存在负圈则会无法确定最小。

代码:

#include<bits/stdc++.h>using namespace std;
const int INF = 0x7ffffff
const int MAX_V=100;//cost[u][v]表示边e=(u,v)的权重(不存在就是INF)
int cost[MAX_V][MAX_V];
int d[MAX_V];
bool used[MAX_V];
int V;void Dijstra(int s){fill(d,d+V,INF);fill(used,used+V,false);d[s]=0;while(true){int v=-1;for(int u=0;u<v;++u){//不断更新,找到尚未使用且最短距离的节点if(!used[u]&&(v==-1||d[u]<d[v])) v=u;}//没有更新就说明更新完了if(v==-1) break;used[v]=true;for(int u=0;u<V;++u){//如果两条节点没有连接就是无穷大,所以就没有更新d[u]=min(d[u],d[v]+cost[v][u]);}}
}int main(){int from,to,cost;int s; fill(cost,cost+MAX_V*MAX_V,INF);for(int i=0;i<V;++i){cost[i][i]=0;}cin>>s;while(cin>>from>>to>>cost){cost[from][to]=cost;}Dijsktra(s);for(int i=0;i<V;++i){printf("%d->%d的花销:%d\n",s,i,d[i]);}return 0;
}

优点与缺点

他的缺点

无法处理负圈,对于负圈还是需要用上Bellman-Ford算法

他的优点

处理比Bellman-Ford算法快一点

可以看出,每次去最短点是要遍历一次的,并且更新的时候也需要遍历完所有边。所以他的优点并没有完全体现出来所以就有了下面的优化。

优化

插入(更新)

对于插入,也就是更新操作中,我们可以使用邻接表来优化

取出

对于取出,我们则可以使用堆这个数据结构完成优化,也就是STL中的优先队列priority_queue实现。
那么上代码:

#include<bits/sdtc++.h>
using namespace std;
const int INF = 0x7fffff;
const int MAX_V=100;
typedef pair<int,int> P; //first是最短距离,second是顶点编号
struct edge{ int to,cost; };int V;
vector<edge> G[MAX_V];
int d[MAX_V];void dijkstra(int s){//STL的priority_queue本身是取最大值的,所以要加greater<TYPE>。priority_queue<P,vector<P>,greater<P>> que;fill(d,d+V,INF);d[s]=0;que.push(0,s);while(!que.empty()){P p = que.top(); que.pop();int v = p.second();if(d[V]<p.first) continue;for(int i=0;i<G[v].size();++i){edge e = G[v][i];if(d[e.to]>d[v]+e.cost){d[e.to]=d[v]+e.cost;que.push({d[e.to],e.to});}}}
}int main(){int from,to,cost;int s; cin>>V;for(int i=0;i<V;++i){int from,e,w;cin>>from>>e>>w;G[from].push_back({e,w});}cin>>s;Dijsktra(s);for(int i=0;i<V;++i){printf("%d->%d的花销:%d\n",s,i,d[i]);}return 0;
}

最后感想

花了两节C语言课,才写完,各位爷可以给我这个小博主点个赞吗?
Orz,下跪了!

你居然不会狄杰斯特算法?惊了!相关推荐

  1. 第7章——狄克特斯拉算法

    算法比较 相比于第6章的广度优先算法计算的是无权图中的最短路径,狄克特斯拉算法计算的是加权图中的最短路径 算法流程 找出最便宜的节点,即可在最短时间内前往的节点. 对于该节点的邻居,检查是否有前往它们 ...

  2. *11.迪杰斯克拉算法

    概念 迪杰斯克拉算法是用来求单源最短路径,计算一个节点到其他所有节点的最短路径.并且要求图中不存在负权边.(简单点讲就是最短路径上的任意两点都是最短路径,有点套娃的思想) 算法步骤: 1.首先把图的一 ...

  3. 狄克斯特拉算法(入门)

    狄克斯特拉算法可以找出加权图中前往X的最短路径. 注意: - 其只适用于有向无环图 - 适用于正权边,负权边的将出错(贝尔曼-福德算法适用于负权边) 步骤: 找出当前最"便宜"的节 ...

  4. 小白的算法初识课堂(part7)--狄克斯特拉算法

    学习笔记 学习书目:<算法图解>- Aditya Bhargava 文章目录 狄克斯特拉算法 具体步骤实现 术语 跳蚤市场 具体步骤实现 负权边 python实现 狄克斯特拉算法 在上一个 ...

  5. 图解算法学习笔记(七):狄克斯特拉算法

    目录 1)使用狄克斯特拉算法 2)术语 3)实现 4)小结 本章内容; 介绍加权图,提高或降低某些边的权重: 介绍狄克斯特拉算法,找出加权图中前往X的最短路径: 介绍图中的环,它导致狄克斯特拉算法不管 ...

  6. 算法(四):图解狄克斯特拉算法

    算法简介 狄克斯特拉算法(Dijkstra )用于计算出不存在非负权重的情况下,起点到各个节点的最短距离 可用于解决2类问题: 从A出发是否存在到达B的路径: 从A出发到达B的最短路径(时间最少.或者 ...

  7. VC++2012编程演练数据结构《31》狄杰斯特拉算法

    狄杰斯特拉算法 Dijkstra(狄杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Dijkstra算法是很 ...

  8. 《算法图解》——狄克斯特拉算法

    前面文章提到,找出段数最少的路径,使用广度优先搜索. 现在要找出最快的路径,(花费最少)使用狄克斯特拉算法. 狄克斯特拉算法包含的四个步骤: (1)找出最便宜的节点,即可在最短时间内前往的节点. (2 ...

  9. 算法图解之狄克斯特拉算法实现

    狄克斯特拉算法用于在加权图中查找最短路径(权重不能为负) '''实现狄克斯特拉算法''' graph = {} graph['start'] = {}#在散列表graph中再建一个散列表为start, ...

最新文章

  1. JavaScript前端框架的思考
  2. 量子位「MEET 2021智能未来大会」启动,邀智能科技企业共探明日行业新格局
  3. 二值化_处理连续型特征:二值化与分段
  4. object-c 随机数总结
  5. thinkphp如何通过php请求接口,thinkphp怎么做json数据接口
  6. [精品]CSAPP Bomb Lab 解题报告(五)
  7. IOS UIPageController
  8. 团队开发之个人博客一
  9. 三种常用的MySQL建表语句
  10. 【小刘带你玩儿前端】什么是跨域以及如何解决?小刘带你轻松拿彻底解决~
  11. 一个选手和小丫姐的搞笑对话
  12. 养生品茶的30个心得
  13. Faster-Rcnn 网络训练医学乳腺DDSM图像不能预测到定位框问题及其训练问题
  14. 2022年证券从业资格投资顾问考试多选题专练及答案
  15. linux识别不了u盘格式,Linux识别不了u盘怎么办
  16. 什么是Watchdog?
  17. Ubuntu 复制文件到远端时错误,Permission denied 失败原因深度探索
  18. 南大计算机学院有几个院士,中国大学两院院士数量排名,看看谁的科研实力最强...
  19. 并行分布式计算 并行计算机体系结构
  20. 区块链技术+二维码,打造爱码物联产品质量溯源软件

热门文章

  1. MySQL慢查询配置和使用
  2. 新浪微博上市好故事难讲
  3. 跟Java面试官对线的一天!唬住就要50K,唬不住就要5K
  4. springmvc全局异常处理
  5. android实现拍照及获取照片上传至接口
  6. python图片显示文本框_用PYTHON以“形式”同时显示图像和文本框
  7. 1142:单词的长度
  8. FA(萤火虫算法)MATLAB源码详细中文注解
  9. 安装win10 找不到固态硬盘
  10. python对整数进行因数分解_浅谈将一个正整数分解质因数的逻辑思维和Python开发设计...