Dijkstra复习
来源:互联网 发布:淘宝菜鸟驿站没有了 编辑:程序博客网 时间:2024/06/01 09:38
看挑战程序设计竞赛上的。
朴素的Dijkstra 如果用邻接矩阵存储,每次需要用O(|V|)的时间找到一个没有被使用过的且距离顶点距离最近的点,然后需要枚举一遍所有的点,这个操作也是O(|V|),一共更新O(|V|)次 一共的复杂度就是O(|V|^2)
朴素的Dijkstra如果用邻接表存储,每次同样需要O(|V|)的时间找到一个没有被使用过的且距离顶点距离最近的点,但是总体只会把所有边枚举一遍O(|E|),一共还是更新O(|V|)次,所以复杂度也是O(|V|^2)
如果用邻接表加上优先队列,那么每次找到一个找到一个没有被使用过的且距离顶点距离最近的点的复杂度就是O(lgV),插入和更新的最坏情况是O(|E|),所以一共的复杂度是O(|E|lg|V|)。需要注意,当|E|≈|V|^2时,使用优先队列的复杂度为O(|V|^2lg|V|) 。
更新:
总结一下dijkstra的适用范围。
标准的dijkstra+heap的,以前写的程序都是在完整循环一次之后会确定从s到当前的最短路,并且这个值不会再改变了,之后的最短路依赖于已经得出最短路的点,这是基于一个贪心思想,即未来的最短路是建立在当前得到最短路的基础上的,这就默认了一个事实,不能存在负权边。 这种写法遇到负权边就要出错。
还有一种是标准写法的变种,它的外层循环是while(pq.size()),也就是说只要优先队列不为空,就会继续更新。假设图中存在一条负权边s->t,那么在s被更新之后,必然枚举它的相邻边t,即使t之前已经被确定了最短距离,只要这个借助s->t的最短距离小于原来已经确定的最短距离,pq就不会为空,所以如果存在负权边s->t,它能创造一个更近的距离,这条负权边不会被忽视。所以这种写法可以正确求出含负权边的图。
但是无论如何都不能用来求含负环的图。
朴素+邻接表代码
#include <iostream>#include <cstdio>#include <cstring>#include <vector>#define INF 0x7fffffffusing namespace std;struct edge{ int to,v; edge(int to,int v):to(to),v(v){} edge(){}};const int maxn = 5005;vector<edge> g[maxn];bool used[maxn];int d[maxn];int V,E;void dijkstra(int s){ d[s]=0; memset(used,0,sizeof(used)); while(true) { int u=-1; for(int v=1;v<=V;v++) if(!used[v]&&(u==-1||d[v]<d[u])) u=v; if(u==-1) break; used[u]=1; for(int i=0;i<(int)g[u].size();i++) d[g[u][i].to]=min(d[g[u][i].to],d[u]+g[u][i].v); }}int main(){ int s; scanf("%d%d%d",&V,&E,&s); for(int i=1;i<=V;i++) { g[i].clear(); d[i]=INF; } for(int i=1;i<=E;i++) { int f,t,v; scanf("%d%d%d",&f,&t,&v); g[f].push_back(edge(t,v));//споРм╪ } dijkstra(s); for(int i=1;i<=V;i++) printf("%d->%d:%d\n",s,i,d[i]); return 0;}Dijkstra+优先队列代码
#include <iostream>#include <cstdio>#include <cstring>#include <vector>#include <queue>#define INF 0x7fffffffusing namespace std;typedef pair<int,int> P;struct edge{ int to,v; edge(int to,int v):to(to),v(v){} edge(){}};const int maxn = 5005;vector<edge> g[maxn];int V,E;int d[maxn];void dijkstra(int s){ priority_queue<P,vector<P>,greater<P> > pq; d[s]=0; pq.push(P(0,s)); while(pq.size()) { P now=pq.top(); pq.pop(); if(now.first>d[now.second]) continue; for(int i=0;i<(int)g[now.second].size();i++) { d[g[now.second][i].to]=min(d[g[now.second][i].to],d[now.second]+g[now.second][i].v); pq.push(P(d[g[now.second][i].to],g[now.second][i].to)); } }}int main(){ int s; scanf("%d%d%d",&V,&E,&s); for(int i=1;i<=V;i++) d[i]=INF; for(int i=1;i<=E;i++) { int f,t,v; scanf("%d%d%d",&f,&t,&v); g[f].push_back(edge(t,v)); } dijkstra(s); for(int i=1;i<=V;i++) printf("%d->%d:%d\n",s,i,d[i]); return 0;}
- Dijkstra复习
- [复习]Dijkstra+堆/SPFA/Dijkstra+优先队列 浣花溪公园
- 算法复习 - Dijkstra算法(迪杰斯特拉算法)
- (复习)图论--最短路--Dijkstra算法
- 蒟蒻复习之-----SPFA,dijkstra
- 一步一步复习数据结构和算法基础-dijkstra算法
- 【算法复习】Dijkstra寻图的最小路径
- [算法第一轮复习] 最短路算法之dijkstra
- 单源最短路径复习--Dijkstra算法和Floyd算法
- dijkstra
- dijkstra
- Dijkstra
- Dijkstra
- DIJKSTRA
- DIJKSTRA
- Dijkstra
- dijkstra
- dijkstra
- 最大流最小割算法入门理解
- c++ 常用库
- 单反相机参数之光圈、快门篇
- android5.0官网编译环境搭建(Initializing a Build Environment)
- memcache熟悉步骤
- Dijkstra复习
- 医疗软件实施入门02
- 《C++Primer》读书笔记(5)
- The typical features of the film faced plywood
- Mac Android签名生成keystore
- 解决“No 'Access-Control-Allow-Origin' header is present on the requested resource.”
- [读书] 暗时间
- RFID第三次作业:RFID系统信号的通信过程
- apache common包中的一些有用的帮助类 --BooleanUtils