part 1.Dijkstra算法是干嘛的

Dijkstra 算法用于求图中任意两点之间的最短路径,或任意一点到其他到其他所有点的最短路径,即单源最短路。Dijkstra 算法只适用于所有边权都为非负数的图,如果边权为负,Dijkstra 算法就无能为力了。


part 2.算法流程

这里用邻接矩阵存图。

  1. 将图分为两个集合:已知最短路成的定点集合 \(P\) 和未知最短路径的集合 \(S\)。用一个 book[] 数组记录那些点在集合 \(P\) 中,book[i]=true表示点 \(i\) 在集合中,book[i]=false 表示点 \(i\) 不在集合中。

  2. 将源点 \(d\) 到自己的最短路径设为 \(0\),其余的设为 \(\infty\)。这里用dis[i]表示点 \(d\) 到点 \(i\) 的最短路径,同时将源点 \(d\) 加入到集合 \(P\) 中。

  3. (1)每次在集合S中选择一个里源点最近(即dis[i]最小)的点 \(i\),将 \(i\) 加入集合 \(P\)(即book[i]=true)。(2)同时考查每一条与 \(i\) 有边相连的点 \(v\),看看能否通过点 \(i\) 将 \(d\) 到 \(v\) 的距离缩短(即dis[v]=min(dis[v],dis[i]+e[i][v]))(也就是松弛)。

  4. 重复第3步,当集合 \(S\) 为空时,算法结束。

code:

// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
#define inf 2147483647
int dis[1005],e[1005][1005];
bool book[1005];
int main()
{
int n,m,i,j,u,v,minh,s,a,b,c;
cin>>n>>m>>s;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(i!=j)
e[i][j]=inf;
for(i=1;i<=m;i++)
{
cin>>a>>b>>c;
if(a!=b) e[a][b]=c;
}
for(i=1;i<=n;i++) dis[i]=e[s][i];
book[s]=true;//2
for(i=1;i<=n-1;i++)
{
minh=inf;
for(j=1;j<=n;j++)
{
if(dis[j]<minh&&book[j]==false)
{
minh=dis[j];
u=j;//3(1)
}
}
book[u]=true;
for(v=1;v<=n;v++)//3(2)
if(e[u][v]<inf)
if(dis[v]>dis[u]+e[u][v])
dis[v]=dis[u]+e[u][v];
}
for(i=1;i<=n;i++) cout<<dis[i]<<" ";
return 0;
}

part 3.还能再优化吗

上述流程的时间复杂度为 \(\mathcal O(n^2)\),如果 \(n\) 大一点,那么就会T飞。

注意到步骤3(2)之和与 \(i\) 周围的边的点松弛,于是我们就可以用邻接表存图,优化算法的常数。

观察到步骤3(1)每次一个一个寻找距离最小的点非常耗时间,于是我们就用一个优先队列来实时存最小的点。(详见代码)

这样就可以将时间复杂度优化到 \(\mathcal O((m+n)\log n)\)。

code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int N=100010,M=100010;//N:点数,M:边数
int head[N],ver[M],edge[M],nxt[M],dis[N];
bool book[N];
int n,m,tot;
priority_queue<pair<int,int> > que;//第一维:距离,第二维:编号
void add(int x,int y,int z)//构建邻接表
{
ver[++tot]=y;
edge[tot]=z;
nxt[tot]=head[x];
head[x]=tot;
}
void Dijkstra()
{
memset(dis,0x3f,sizeof(dis));
memset(book,0,sizeof(book));
dis[1]=0;
que.push(make_pair(0,1));
while(que.size())
{
int x=que.top().second; que.pop();
if(book[x]) continue;
book[x]=true;//标记
for(int i=head[x];i;i=nxt[i])
{
int y=ver[i],z=edge[i];
if(dis[y]>dis[x]+z)
{
dis[y]=dis[x]+z;
que.push(make_pair(-dis[y],y));
}
}
}
}
int main()
{
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d %d %d",&x,&y,&z);
add(x,y,z);
}
Dijkstra();
for(int i=1;i<=n;i++) printf("%d ",dis[i]);
return 0;
}

Dijkstra堆优化+邻接表的更多相关文章

  1. 魔法效果——dijkstra+堆(邻接表存储)

    dijkstra本身每次要for一遍,才能找出最小的节点,但用了堆之后,直接取出堆首就可以了. 但要注意的一点是,c++自带的stl里的priority_queue本身是先入大出的,而我们要求的是最小 ...

  2. dijkstra堆优化(multiset实现->大大减小代码量)

    例题: Time Limit: 1 second Memory Limit: 128 MB [问题描述] 在电视时代,没有多少人观看戏剧表演.Malidinesia古董喜剧演员意识到这一事实,他们想宣 ...

  3. POJ 2502 - Subway Dijkstra堆优化试水

    做这道题的动机就是想练习一下堆的应用,顺便补一下好久没看的图论算法. Dijkstra算法概述 //从0出发的单源最短路 dis[][] = {INF} ReadMap(dis); for i = 0 ...

  4. Bzoj 2834: 回家的路 dijkstra,堆优化,分层图,最短路

    2834: 回家的路 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 62  Solved: 38[Submit][Status][Discuss] D ...

  5. POJ2387(dijkstra堆优化)

    Til the Cows Come Home Bessie is out in the field and wants to get back to the barn to get as much s ...

  6. hdu 2544 单源最短路问题 dijkstra+堆优化模板

    最短路 Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submis ...

  7. 深入理解dijkstra+堆优化

    深入理解dijkstra+堆优化 其实就这几种代码几种结构,记住了完全就可以举一反三,所以多记多练多优化多思考. Dijkstra   对于一个有向图或无向图,所有边权为正(边用邻接矩阵的形式给出), ...

  8. POJ 1511 - Invitation Cards 邻接表 Dijkstra堆优化

    昨天的题太水了,堆优化跑的不爽,今天换了一个题,1000000个点,1000000条边= = 试一试邻接表 写的过程中遇到了一些问题,由于习惯于把数据结构封装在 struct 里,结果 int [10 ...

  9. POJ-2387.Til the Cows Come Home.(五种方法:Dijkstra + Dijkstra堆优化 + Bellman-Ford + SPFA + Floyd-Warshall)

    昨天刚学习完最短路的算法,今天开始练题发现我是真的菜呀,居然能忘记邻接表是怎么写的,真的是菜的真实...... 为了弥补自己的菜,我决定这道题我就要用五种办法写出,并在Dijkstra算法堆优化中另外 ...

随机推荐

  1. Cesium原理篇:GroundPrimitive【转】

    今天来看看GroundPrimitive,选择GroundPrimitive有三个目的:1 了解GroundPrimitive和Primitive的区别和关系 2 createGeometry的特殊处 ...

  2. 根据motif binding来确定target gene | HOMER | FIMO | MEME

    主流的motif数据库 JASPAR dbcorrdb - SCENIC使用的 TRANSFAC® 7.0 Public 2005 and TRANSCompel 7.0 Public 2005 - ...

  3. centos如何添加ftp目录

    检查Centos服务器中是否安装了vsftpd rpm -qa |grep vsftpd 如果没有显示则没有安装 2.安装vsftpd yum -y install vsftpd 3.打开vsftpd ...

  4. RSA前台加密后台解密的应用

    写在前面 项目安全测试需要将登录功能修改, AES加密不符合要求, 现改为RSA非对称加密.(将登录密码加密后传给后台, 后台解密后再进行一系列的校验) .期间遇到了前台js加密但是后台解密失败的问题 ...

  5. mac opencv 提示摄像头权限问题

    通常在iOS开发下,我们的app需要在Info.plist文件中配置所需要的各种限制:如摄像头权限: 本次我们在mac下创建了一个command line 程序,并且设定是c++开发,并配置了open ...

  6. CentOS 7.5 安装Oracle 11gR2 86%报错:Error in invoking target 'agent nmhs' of makefile

    解决方案: 不要关闭安装过程,另外打开终端窗口,将ins_emagent.mk文件中的 (MK_EMAGENT_NMECTL)更改为$(MK_EMAGENT_NMECTL) -lnnz11,然后在安装 ...

  7. Android如何屏蔽home键和recent键

    最近在做一个项目的时候,进入一个 Activity后需要暂时屏蔽掉home键和recent键(back键可以在onKeyDown里面处理),网上找了半天,都是针对旧版本android的方法,andro ...

  8. win10 搜索栏输入后长期没反应

    博客转载自:https://blog.csdn.net/qq_40875146/article/details/81742533 Get-AppXPackage -Name Microsoft.Win ...

  9. Python 处理异常栈模块——traceback 模块

    异常捕捉 通常我们在项目中,针对异常的捕捉会使用 try + except,基本形式如下: try: # 主代码 except IndexError as e: # 索引异常时执行这里 logger. ...

  10. jzy3D从入门到弃坑_2使用jzy3D0.9画2D散点图

    jzy3D从入门到弃坑_2 使用jzy3D0.9画2D散点图 觉得有用的话,欢迎一起讨论相互学习~Follow Me 在上一节中安装jzy3D 0.9版本并且运行了3D的例子 https://blog ...