博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
c++最短路经典问题
阅读量:7099 次
发布时间:2019-06-28

本文共 2212 字,大约阅读时间需要 7 分钟。

一提起最短路,各位oier会想到什么呢?

floyd,spfa,dij,或是bellman-ford?

其实,只要学会一种算法,大部分最短路问题就能很快解决了。

他就是堆优化的dijkstra。

首先,先讲一下dij是怎么求最短路的。

Dijkstra是基于一种贪心的策略,首先用数组dis记录起点到每个结点的最短路径,再用一个数组保存已经找到最短路径的点

然后,从dis数组选择最小值,则该值就是源点s到该值对应的顶点的最短路径,并且把该点记为已经找到最短路

此时完成一个顶点,再看这个点能否到达其它点(记为v),将dis[v]的值进行更新

不断重复上述动作,将所有的点都更新到最短路径

这种算法实际上是O(n^2)的时间复杂度,但我们发现在dis数组中选择最小值时,我们可以用一些数据结构来进行优化。

其实我们可以用STL里的堆来进行优化,堆相对于线段树以及平衡树有着常数小,码量小等优点,并且堆的一个妙妙的性质就是可以在nlogn的时限内满足堆顶是堆内元素的最大(小)值,之不正是我们要的嘛?

但是呢,dij处理不了负边,所以当题目出现负边时,dij就不能用了。

但反过来说,只要题目没负边,SPFA是一定会被卡的!

下面上代码:

#include
using namespace std;#define maxn 10005#define maxm 500005#define INF 1234567890inline int read(){ int x=0,k=1; char c=getchar(); while(c<'0'||c>'9'){
if(c=='-')k=-1;c=getchar();} while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar(); return x*k;}struct Edge{ int u,v,w,next;}e[maxm];int head[maxn],cnt,n,m,s,vis[maxn],dis[maxn];struct node{ int w,now; inline bool operator <(const node &x)const //重载运算符把最小的元素放在堆顶(大根堆) { return w>x.w;//这里注意符号要为'>' }};priority_queue
q;//优先队列,其实这里一般使用一个pair,但为了方便理解所以用的结构体inline void add(int u,int v,int w){ e[++cnt].u=u; //这句话对于此题不需要,但在缩点之类的问题还是有用的 e[cnt].v=v; e[cnt].w=w; e[cnt].next=head[u]; //存储该点的下一条边 head[u]=cnt; //更新目前该点的最后一条边(就是这一条边)}//链式前向星加边void dijkstra(){ for(int i=1;i<=n;i++) { dis[i]=INF; } dis[s]=0; //赋初值 q.push((node){
0,s}); while(!q.empty()) //堆为空即为所有点都更新 { node x=q.top(); q.pop(); int u=x.now; //记录堆顶(堆内最小的边)并将其弹出 if(vis[u]) continue; //没有遍历过才需要遍历 vis[u]=1; for(int i=head[u];i;i=e[i].next) //搜索堆顶所有连边 { int v=e[i].v; if(dis[v]>dis[u]+e[i].w) { dis[v]=dis[u]+e[i].w; //松弛操作 q.push((node){dis[v],v}); //把新遍历到的点加入堆中 } } }}int main(){ n=read(),m=read(),s=read(); for(int i=1,x,y,z;i<=m;i++) { x=read(),y=read(),z=read(); add(x,y,z); } dijkstra(); for(int i=1;i<=n;i++) { printf("%d ",dis[i]); } return 0;}

谢谢大家!

转载于:https://www.cnblogs.com/mxrmxr/p/9851795.html

你可能感兴趣的文章
8月11日全球域名商(国际域名)解析新增保有量TOP20
查看>>
树莓派开机自动发射热点
查看>>
你必须了解的Session的本质
查看>>
我的友情链接
查看>>
关于linux mount访问windows共享出错问题
查看>>
firebug扩展组件总结归纳 pagespeed 和 yslow
查看>>
yum管理工具
查看>>
Spring Boot (七) 集成Swagger
查看>>
记录一行一码
查看>>
跨越操作系统对X GUI连接
查看>>
Android Runnable 运行在那个线程
查看>>
在ubuntu下搭建eclipse3.7的android开发环境
查看>>
docker安装jdk,tomcat
查看>>
Win10 禁用 WPS 各个软件的自动更新
查看>>
RESTful API 设计指南
查看>>
第一次在Linux系统上编译TCC的Android SDK记实
查看>>
我的友情链接
查看>>
技术博客2014年1月份头条记录
查看>>
KeyMob移动广告聚合平台简介
查看>>
我的友情链接
查看>>