算法思想:

  类似最小生成树的贪心算法,从起点 v每次新拓展一个距离最小的点,再以这个点为中间点,更新起点到其他点的距离。

算法实现:

  需要定义两个一维数组:①vis[ i ] 表示是否从源点到顶点 i 的最短距离。②用d[ i ] 记录源点v0到顶点 i 的距离值。

  具体步骤如下:

  (1)初始化 d[ v0 ] = 0 ,源点v0到其他点的距离值 d[ i ] = ∞ 。

  (2)经过 n 次如下操作,最后得到 v0 到 n 个顶点的最短距离:

    ①选择一个未标记的点 v 并且 d[ v ] 的值是最小的;

    ②标记点 v ,即 vis[ v ] = 1;

    ③以 k 为中间点,修改源点 v到其他为标记的点 j 的距离值 d[ j ]。

算法复杂度:

  朴素版的复杂度为 O(n2),因为每次查找未标记的节点需耗时 O(n),堆优化后的Dijkstra的复杂度可以降为 O( (n+m) log m )。

算法模板:

①朴素的Dijkstra

#include<bits/stdc++.h>
using namespace std;
struct Edge//前向星存边
{
int to;//此边的子节点
int w;//此边的权值
int next;//与它最近的父节点一样的边的编号
}edge[];
int head[];//以某点为父节点引出的最后一条边
int cnt=;//边编号
inline void add(int x,int y,int w)//存边
{
cnt++;
edge[cnt].to=y;
edge[cnt].w=w;
edge[cnt].next=head[x];
head[x]=cnt;//更新head
}
int main()
{
bool visit[]={};//是否作为过起点
long long dis[];//距离
int n,m,s;
int x,y,w;
scanf("%d%d%d",&n,&m,&s);
for(int i=;i<=n;i++)dis[i]=;
for(int i=;i<m;i++)
{
scanf("%d%d%d",&x,&y,&w);
add(x,y,w);
}
int curr=s;
dis[s]=;
long long minn;
while(!visit[curr])//即搜完整张图
{
visit[curr]=true;//已做为过起点
for(int i=head[curr];i!=;i=edge[i].next)//链式前向星搜边
{
if(!visit[edge[i].to]&&dis[edge[i].to]>dis[curr]+edge[i].w)
dis[edge[i].to]=dis[curr]+edge[i].w;//更新操作
}
minn=;
for(int i=;i<=n;i++)
{
if(!visit[i]&&minn>dis[i])//取新的最小值
{
minn=dis[i];
curr=i;
}
}//
}
for(int i=;i<=n;i++)printf("%lld ",dis[i]);
return ;
}

②堆优化的Dijkstra

#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<string>
#include<iostream>
#include<algorithm>
#include<stack>
#include<deque>
#include<set>
#include<map>
#include<vector>
#include<fstream>
#include<queue>
using namespace std;
#define maxn 100010
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q;//定义一个小根堆(优先队列)
int n,m,cnt,w;
int head[maxn],d[maxn],vis[maxn];
//d数组表示点i和起点之间的距离,vis记录点i是否已确定,head是前向星存边~
inline int read()
{
char kr=;
char ls;
for(;ls>''||ls<'';kr=ls,ls=getchar());
int xs=;
for(;ls>=''&&ls<='';ls=getchar())
{
xs=xs*+ls-;
}
if(kr=='-') xs=-xs;
return xs;
}//快读
struct hh
{
int nex;
int to;
int dis;
}t[maxn<<];//前向星!
inline void add(int nex,int to,int dis)
{
t[++cnt].to=to;
t[cnt].dis=dis;
t[cnt].nex=head[nex];
head[nex]=cnt;
}//存边!
inline void dijkstra(int w)
{
memset(d,0x3f3f3f3f,sizeof(d));//初始化
memset(vis,,sizeof(vis));
q.push(make_pair(,w));//起点入队(堆)了
d[w]=;//自己到自己,距离0
while(!q.empty())//队(堆)不是空的,此时距离起点最小的 点在队首(堆顶)
{
int u=q.top().second;//u:找到了!就是这个点!
q.pop();//出队(堆),去履行更新其他点的光荣义务
if(vis[u]) continue;//如果这是一个已经确定过的点 ,跳过
vis[u]=;
for(int v=head[u];v;v=t[v].nex)//遍历一遍这个点连向的点,更新最短路
{
if(d[t[v].to]>d[u]+t[v].dis&&!vis[t[v].to])
{
d[t[v].to]=d[u]+t[v].dis;
q.push(make_pair(d[t[v].to],t[v].to));//被更新了,进去
}
}
}
}
int main()
{
int xx,yy,ww;
n=read();m=read();w=read();
for(int i=;i<=m;i++)
{
xx=read();yy=read();ww=read();
add(xx,yy,ww);//有向图
}
dijkstra(w);
for(int i=;i<=n;i++)
{
printf("%d ",d[i]);
}//输出
return ;
}

巩固:

  ① Dijkstra弱化版

  ② Dijkstra加强版

单源最短路——Dijkstra模板的更多相关文章

  1. 利用分支限界法求解单源最短路(Dijkstra)问题

    分支限界法定义:采用Best fist search算法,并使用剪枝函数的算法称为分支界限法. 分支限界法解释:按Best first的原则,有选择的在其child中进行扩展,从而舍弃不含有最优解的分 ...

  2. 【算法】单源最短路——Dijkstra

    对于固定起点的最短路算法,我们称之为单源最短路算法.单源最短路算法很多,最常见的就是dijkstra算法. dijkstra主要用的是一种贪心的思想,就是说如果i...s...t...j是最短路,那么 ...

  3. 牛客编程巅峰赛S1第6场 - 黄金&钻石&王者 C.星球游戏 (单源最短路,Dijkstra)

    题意:有\(n\)个点,\(m\)条双向边,两个方向的权值都是相等的,可以从\(A\)中的某个点出发走到\(B\)中的某个点,求所有路径中的最短距离,如果A和B中没有点联通,则输出\(-1\). 题解 ...

  4. 洛谷 P5837 [USACO19DEC]Milk Pumping G (单源最短路,dijkstra)

    题意:有一\(n\)个点,\(m\)条边的双向图,每条边都有花费和流量,求从\(1\)~\(n\)的路径中,求\(max\frac{min(f)}{\sum c}\). 题解:对于c,一定是单源最短路 ...

  5. 单源最短路——dijkstra算法

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

  6. 单源最短路dijkstra算法&&优化史

    一下午都在学最短路dijkstra算法,总算是优化到了我能达到的水平的最快水准,然后列举一下我的优化历史,顺便总结总结 最朴素算法: 邻接矩阵存边+贪心||dp思想,几乎纯暴力,luoguTLE+ML ...

  7. P4779 【模板】单源最短路径(标准版)单源最短路Dijkstra

    题目描述 给定一个$n$个点,$m$条有向边的带非负权图,请你计算从$s$出发,到每个点的距离. 数据保证你能从$s$出发到任意点. 输入格式 第一行为三个正整数$n,m,s$. 第二行起$m$行,每 ...

  8. hdoj 1874 畅通工程续(单源最短路+dijkstra)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1874 思路分析:该问题给定一个无向图.起始点和终点,要求求出从起始点到终点的最短距离: 使用Dijks ...

  9. 单源最短路Dijkstra算法——matlab实现

    迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止. 基本思想 通过Dijk ...

随机推荐

  1. 数据库中的undo日志、redo日志

    MySQL中有六种日志文件,分别是:重做日志(redo log).回滚日志(undo log).二进制日志(binlog).错误日志(errorlog).慢查询日志(slow query log).一 ...

  2. Redis慢查询日志学习功能

    慢查询日志 什么是SLOW LOG? Slow log是Redis用来记录查询执行时间超过给定时长的命令请求的日志系统.查询执行时间指的是不包括像客户端响应(talking).发送回复等IO操作,而单 ...

  3. 每日linux命令学习-历史指令查询(history、fc、alias)

    linux历史机制对命令行中输入的命令进行编号并依此保存,以维护命令历史.登录会话期间输入的命令保存在shell内存中,若终止命令则添加至历史文件. 1. 箭头符号方向键 使用键盘上的箭头方向键可以从 ...

  4. java日志

    http://blog.csdn.net/u013628152/article/details/43538299 http://blog.csdn.net/isea533/article/detail ...

  5. Java日志 #01# 入门

    很多人在学习完一个东西之后就会忘掉自己作为初学者时的体验.. 例如刚接触git的时候自己也是一头雾水,然后别人问起来,老是会说:xxxx#!@#,就是这么回事儿,有什么不好懂的. 其实从不懂到懂,再到 ...

  6. python字符格式化

    使用%格式化字符串 字符串格式化使用格式化操作符即百分号. 在%号的左侧放置一个字符串(格式化字符串),而右侧则放置希望格式化的值. In [17]: name = "wxz" I ...

  7. js 实现几分钟前、几小时前、几天前,以及几分钟后、几小时后、几天前后

    js 实现几分钟前.几小时前.几天前,以及几分钟后.几小时后.几天前后 /* * * 把传入的时间戳与当前时间比较,计算几分钟前.几小时前.几天前,以及几分钟后.几小时后.几天前后 * unixtim ...

  8. 最新版Postman的下载及安装

    1. 操作环境 Windows Windows 7旗舰版 64位  , Windows 10专业版 Postman Postman-win64-5.1.3-Setup.exe 2. Postman的资 ...

  9. listen()函数中backlog参数分析

    实例分析1 将服务器端的listen函数backlog设置为2,用20个客户端与服务器建立连接,查看连接的建立情况. 服务器代码: #include <stdio.h> #include& ...

  10. zookeeper各种报错、原因及解决方法汇总(持续更新)

    [root@iZ23nn1p4mjZ zookeeper-3.4.10]# bin/zkCli.sh -server localhost:2181,localhost:2182,localhost:2 ...