用优先队列优化的Dijkstra

1找到最短距离已经确认的顶点,从它出发更新相邻顶点的最短距离

2此后不需要关心1中的“最短距离已经确认的顶点”

堆中元素共有O(V)个,更新和取出都有O(E)次,每次更新或取出堆的维护时间是O(logV),因此该算法的时间复杂度为O(ElogV).

本样例所用输入输出

输入描述

输入两个整数V,E,分别表示有向图(无向图就多添加一倍的边)的的节点数,和边数

接下来E行,每行三个整数,分别表示,无向图边的连个端点以及权值

输出描述

输出一行V个整数,表示每个点到起点的最短路径

输入样例

7 10
1 2 2
1 3 5
2 3 4
3 4 2 
2 4 6 
4 6 1
2 5 10
5 6 3
5 7 5
6 7 9

输出样例

有向:0 2 5 7 12 8 17
无向:0 2 5 7 11 8 16


#include<iostream>
#include<vector>
#include<queue>
using namespace std;
const int MAX_V=10005;
const int INF=0x3f3f3f;
struct edge{int to;//边的终点 int cost;//权值edge(int t,int c){to=t;cost=c;}
};
typedef pair<int,int> P;//first是最短距离,second是顶点编号
int V;//顶点数
int E;//边数
vector<edge> G[MAX_V];
int d[MAX_V];void read(){int start,to,cost;scanf("%d%d",&V,&E);for(int i=0;i<E;i++){scanf("%d%d%d",&start,&to,&cost);G[start].push_back(edge(to,cost));G[to].push_back(edge(start,cost));//加上这句,无向图}
}
void dijkstra(int s){//通过指定greater<P>参数,堆按照first从小到大的顺序取出值priority_queue<P,vector<P>,greater<P> > que;//优先队列里存的都是最短距离已经确认的顶点 fill(d,d+V+1,INF);d[s]=0;que.push(P(0,s));//起点,起点到起点的最短距离是确定的(0) while(!que.empty()){P p=que.top();que.pop();//每次取出容器中已经确定的离起点最近的点 printf("取出点%d\n",p.second); int v=p.second;if(d[v]<p.first)continue;//表示该点入队不只一次(即之前有多个点都可以到达它),那么d[v]也可能更新了不只一次,//而每次更新都会使d[v]更小,显然这个p.first是其中一次更新,但不是最小的那个,而最小的//那个在此之前就出队了,所以不必再用这条记录继续往下更新了 for(int i=0;i<G[v].size();i++){//扫描其所有相邻的顶点,并更新他们的最短距离d[i] edge e=G[v][i];if(d[e.to]>d[v]+e.cost){printf("d[%d]:%d>d[%d]:%d+%d_to_%d_cost:%d\t更新d[%d]为%d\t%d入队\n",e.to,d[e.to],v,d[v],v,e.to,e.cost,e.to,d[v]+e.cost,e.to);d[e.to]=d[v]+e.cost;//d[v]是已经确定的que.push(P(d[e.to],e.to));//更新后最短距离已经确认的点入队,优先队列里自动维护,队头是最小的那个 }} }
}
int main(){read();dijkstra(1);for(int i=1;i<=V;i++)printf("%d ",d[i]);return 0;
}

下面为注释更详细的版本

/*
7 10
1 2 2
1 3 5
2 3 4
3 4 2
2 4 6
4 6 1
2 5 10
5 6 3
5 7 5
6 7 90 2 5 7 12 8 17
*/
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
const int MAX_V=10005;
const int INF=0x3f3f3f;
struct edge{int to;//边的终点 int cost;//权值edge(int t,int c){to=t;cost=c;}
};
typedef pair<int,int> P;//first是该点入队时的最短距离,second是顶点编号
int V;//顶点数
int E;//边数
vector<edge> G[MAX_V];
int d[MAX_V];void read(){int start,to,cost;scanf("%d%d",&V,&E);for(int i=0;i<E;i++){scanf("%d%d%d",&start,&to,&cost);G[start].push_back(edge(to,cost));}
}
void dijkstra(int s){//通过指定greater<P>参数,堆按照first从小到大的顺序取出值priority_queue<P,vector<P>,greater<P> > que;//优先队列里存的都是最短距离已经确认的顶点 /*priority_queue 对于基本类型的使用方法相对简单。他的模板声明带有三个参数:priority_queue<Type, Container, Functional>其中Type 为数据类型, Container 为保存数据的容器,Functional 为元素比较方式。Container 必须是用数组实现的容器,比如 vector, deque 但不能用 list.STL里面默认用的是 vector. 比较方式默认用 operator< , 所以如果你把后面俩个参数缺省的话,优先队列就是大顶堆,队头元素最大。如果要用到小顶堆,则一般要把模板的三个参数都带进去。STL里面定义了一个仿函数 greater<>,对于基本类型可以用这个仿函数声明小顶堆p1 < p2;  两个pair对象间的小于运算,其定义遵循字典次序:如 p1.first < p2.first 或者 !(p2.first < p1.first) && (p1.second < p2.second) 则返回true。pair详解 转https://blog.csdn.net/sevenjoin/article/details/81937695*/fill(d,d+V+1,INF);d[s]=0;que.push(P(0,s));//起点,起点到起点的最短距离是确定的(0) while(!que.empty()){P p=que.top();que.pop();//每次取出容器中已经确定的离起点最近的点 //printf("取出点%d\n",p.second); int v=p.second;if(d[v]<p.first)continue;//表示该点入队不只一次(即之前有多个点都可以到达它),那么d[v]也可能更新了不只一次,//而每次更新都会使d[v]更小,显然这个p.first是其中一次更新,但不是最小的那个,而最小的//那个在此之前就出队了,所以不必再用这条记录继续往下更新了 /*这里是队的取出情况 取出点1d[2]:4144959>d[1]:0+1_to_2_cost:2       更新d[2]为2     2入队d[3]:4144959>d[1]:0+1_to_3_cost:5       更新d[3]为5     3入队取出点2d[4]:4144959>d[2]:2+2_to_4_cost:6       更新d[4]为8     4入队d[5]:4144959>d[2]:2+2_to_5_cost:10      更新d[5]为12    5入队取出点3d[4]:8>d[3]:5+3_to_4_cost:2             更新d[4]为7     4入队取出点4  这个是P(7,4) d[6]:4144959>d[4]:7+4_to_6_cost:1       更新d[6]为8     6入队取出点4  这个是P(8,4),而d[4]已经在第65行时被更新为7<p.first:8 所以continue 取出点6d[7]:4144959>d[6]:8+6_to_7_cost:9       更新d[7]为17    7入队取出点5取出点7*/for(int i=0;i<G[v].size();i++){//扫描其所有相邻的顶点,并更新他们的最短距离d[i] edge e=G[v][i];if(d[e.to]>d[v]+e.cost){//printf("d[%d]:%d>d[%d]:%d+%d_to_%d_cost:%d\t更新d[%d]为%d\t%d入队\n",e.to,d[e.to],v,d[v],v,e.to,e.cost,e.to,d[v]+e.cost,e.to);d[e.to]=d[v]+e.cost;//d[v]是已经确定的que.push(P(d[e.to],e.to));//更新后最短距离已经确认的点入队,优先队列里自动维护,队头是最小的那个 }} }
}
int main(){read();dijkstra(1);for(int i=1;i<=V;i++)printf("%d ",d[i]);return 0;
}

参考资料:挑战程序设计竞赛P102

单源最短路径 Dijkstra+优先队列相关推荐

  1. 分支限界法:单源最短路径--dijkstra算法

    单源最短路径–dijkstra算法 前面已经多次介绍过dijkstra算法是贪心算法,是动态规划,实际上可以从分支限界的角度来理解: 分支限界法 分支限界法,实际上就是回溯法,一般意义的回溯法是基于深 ...

  2. 数据结构----单源最短路径Dijkstra

    数据结构----单源最短路径Dijkstra 原理:参考趣学数据结构 代码: stack.h 栈代码 #pragma once #include<stdio.h> #define maxS ...

  3. 单源最短路径-分支限界法-优先队列式分支限界法-Dijkstra

    问题描述: 给定一个带权有向图G = (V, E), 其中每条边的权是非负实数.另外,还给定V中的一个顶点,称为源.现在要计算源到所有其他各定点的最短长度.这里路的长度是指路上各边权之和.这个问题通常 ...

  4. 数据结构与算法—单源最短路径dijkstra算法

    介绍 对于dijkstra算法,很多人可能感觉熟悉而又陌生,可能大部分人比较了解bfs和dfs,而对dijkstra和floyd算法可能知道大概是图论中的某个算法,但是可能不清楚其中的作用和原理,又或 ...

  5. JAVA编程求单源最短路径_【算法】单源最短路径——dijkstra算法

    一,概念 单源最短路径 给定一个带权有向图G=(V,E),其中每条边的权是一个实数.另外,还给定V中的一个顶点,称为源.要计算从源到其他所有各顶点的最短路径长度.这里的长度就是指路上各边权之和.这个问 ...

  6. 单源最短路径 dijkstra

    dijkstra是单源最短路径算法,要两个数组来维护需要的信息 dis[i]用来维护起始点到i点的最短距离,初始化为一个很大的数字 0x3f3f3f3f vis[i]用来维护是否访问过该点,初始化为0 ...

  7. 单源最短路径 dijkstra()

    前言 首先,单源最短路径问题(Single Source Shortest Path , SSSP 问题)是说: 给定一张有向图 G= (V,E) , V 是这个图的点集, E = 是边集 , 节点以 ...

  8. dijkstra 算法_数据结构与算法—单源最短路径dijkstra算法

    介绍 对于dijkstra算法,很多人可能感觉熟悉而又陌生,可能大部分人比较了解bfs和dfs,而对dijkstra和floyd算法可能知道大概是图论中的某个算法,但是可能不清楚其中的作用和原理,又或 ...

  9. 单源最短路径-Dijkstra(迪杰斯特拉算法)

    迪杰斯特拉算法时间复杂度为O(n^2),其中n为顶点个数. 该算法用于求单源最短路径.并且图中的边不允许带负权值. #include <iostream> using namespace ...

最新文章

  1. 2017年云计算的6大趋势
  2. java web 自定义标签_如何在JavaWeb程序中使用自定义标签
  3. 这种个性化可视化图也太可爱了吧!
  4. BEGIN-1 A+B问题
  5. 干掉 Swagger,试试这个!
  6. Linux系统编程35:多线程之如何理解Linux中的线程以及轻量级进程LWP
  7. 父子类之间,成员函数重写、重载以及重定义的区别
  8. 怎样完整的转换PDF格式文件
  9. 计算机网络笔记(一):网络基本构成
  10. CDOJ 796 DAGE(Big Brother)
  11. 关于花瓣网header条的思考
  12. 关于解决Ubuntu下apt-get的Unmet dependencies依赖错误
  13. NLM-P (使用积分图像进行算法的优化)
  14. python编写电子菜单_python 写三级菜单
  15. 「转行程序员」30岁想转行还能做什么?月入两万职位大比拼
  16. Java小试牛刀—数组
  17. 文本域 自定义下拉框 支持模糊检索 关键字高亮 上下选择
  18. 东京电力公司TEPCO投资区块链初创企业,目标系统去中心化
  19. 关于“ROS2 Topic-Statistics-Tutorial编译出错”的思考2
  20. 求推荐一款带日历的电脑桌面记事便签

热门文章

  1. Git版本控制管理——基本Git概念
  2. 国产 TF232RL 驱动
  3. input搜索框 php,html搜索框怎么设置?html搜索框input标签的使用方法实例
  4. SSL 3.0 安全漏洞修复方法
  5. 企业承担社会责任的必要性
  6. tex liv模板_微软向所有人开放Liv​​e Mesh
  7. 下面哪个选项不是linux服务器,复习题及解答1
  8. pandas中使用fillna函数填充NaN值
  9. Linux-DNS服务器搭建
  10. 二叉排序树(二叉搜索树)