【Dijkstra】
【摘自】:华山大师兄,推荐他的过程动画~
定义
Dijkstra算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。注意该算法要求图中不存在负权边。
问题描述:在无向图 G=(V,E) 中,假设每条边 E[i] 的长度为 w[i],找到由顶点 V0 到其余各点的最短路径。(单源最短路径)
算法描述
1)算法思想:设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组,第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径 , 就将加入到集合S中,直到全部顶点都加入到S中,算法就结束了),第二组为其余未确定最短路径的顶点集合(用U表示),按最短路径长度的递增次序依次把第二组的顶点加入S中。在加入的过程中,总保持从源点v到S中各顶点的最短路径长度不大于从源点v到U中任何顶点的最短路径长度。此外,每个顶点对应一个距离,S中的顶点的距离就是从v到此顶点的最短路径长度,U中的顶点的距离,是从v到此顶点只包括S中的顶点为中间顶点的当前最短路径长度。
算法步骤
a.初始时,S只包含源点,即S={v},v的距离为0。U包含除v外的其他顶点,即:U={其余顶点},若v与U中顶点u有边,则<u,v>正常有权值,若u不是v的出边邻接点,则<u,v>权值为∞。
b.从U中选取一个距离v最小的顶点k,把k,加入S中(该选定的距离就是v到k的最短路径长度)。
c.以k为新考虑的中间点,修改U中各顶点的距离;若从源点v到顶点u的距离(经过顶点k)比原来距离(不经过顶点k)短,则修改顶点u的距离值,修改后的距离值的顶点k的距离加上边上的权。
d.重复步骤b和c直到所有顶点都包含在S中。
实例
对下图中的有向图,应用Dijkstra算法计算从源顶点1到其它顶点间最短路径的过程列在下表中。


模板
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
const int MAX_V = ;
const int inf = 0x3f3f3f3f; typedef pair<int, int> pii;
struct Dijkstra //封装dijkstra算法
{
struct Edge //定义边的结构体
{
int from, to, cost;
Edge() {}
Edge(int a, int b, int c) : from(a), to(b), cost(c) {}
};
int n, m;
vector<Edge> G[MAX_V]; //边集合
bool vis[MAX_V];
int d[MAX_V];
int prev[MAX_V];
void init(int n) //初始化,清空邻接表和边集合
{
this->n = n;
for(int i = ; i <= n; i++)
{
G[i].clear();
}
}
void add(int from, int to, int dist) //建图
{
G[from].push_back(Edge(from,to,dist));
}
void dijkstra(int s)
{
priority_queue<pii, vector<pii>, greater<pii> > q;
memset(d, inf, sizeof(d));
memset(prev, -, sizeof(prev));
d[s] = ;
q.push(pii(, s)); while(!q.empty())
{
pii p = q.top(); q.pop();
int v = p.second;
if(d[v] < p.first) continue;
for(int i = ; i < G[v].size(); i++)
{
Edge e = G[v][i];
if(d[e.to] > d[e.from]+e.cost)
{
d[e.to] = d[e.from]+e.cost;
q.push(pii(d[e.to], e.to));
prev[e.to] = e.from;
}
}
}
}
vector<int> Get_Path(int t)
{
vector<int> path;
for(; t != -; t = prev[t])
path.push_back(t);
reverse(path.begin(), path.end());
return path;
}
} D; int main()
{
int T;
scanf("%d", &T);
for(int kase = ; kase <= T; kase++)
{
int V, E;
scanf("%d%d", &V, &E);
D.init(V);
for(int i = ; i < E; i++)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
D.add(u, v, w); D.add(v, u, w);
}
int t; scanf("%d", &t);
D.dijkstra(t);
printf("Case %d:\n", kase);
vector<int> path = D.Get_Path(); for(int i = ; i < V; i++)
{
if(D.d[i] >= inf)
printf("Impossible\n");
else
printf("%d\n", D.d[i]);
}
}
return ;
}
封装到class中
STL priority_queue实现:复杂度O(|E|·log|V|)
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
const int MAX_V = ;
const int inf = 0x3f3f3f3f;
int d[MAX_V];
int used[MAX_V];
int cost[MAX_V][MAX_V];
int prev[MAX_V];
int V, E; void Dijkstra(int s) //Source is the source,M is the number of point;
{
memset(used, , sizeof(used));
memset(prev, -, sizeof(prev));
memset(d, inf, sizeof(d));
d[s] = ; while(true)
{
int v = -;
for(int u = ; u < V; u++)
{
if(!used[u] && (v == - || d[u] < d[v])) v = u;
}
if(v == -) break;
used[v] = true;
for(int u = ; u < V; u++)
{
int tmp = max(d[u], cost[v][u]);
d[u] = max(d[u], cost[v][u]);
prev[u] = v;
}
}
} vector<int> Get_Path(int t)
{
vector<int> path;
for(; t != -; t = prev[t])
path.push_back(t);
reverse(path.begin(), path.end());
return path;
}
邻接矩阵
邻接矩阵实现:复杂度O(|V|2)
【Dijkstra】的更多相关文章
- HDU 3790 最短路径问题【Dijkstra】
题意:给出n个点,m条边,每条边的长度d和花费p,给出起点和终点的最短距离和花费,求最短距离,如果有多个最短距离,输出花费最少的 在用dijkstra求最短距离的时候,再用一个f[]数组保存下最少花费 ...
- HDU 2066 一个人的旅行【Dijkstra 】
题意:给出s个起点,d个终点,问从这些起点到达终点的最短距离 因为有多个起点,所以把这多个起点的值设为0 哎= =改了好久的说= = 是因为在代码里面的t,不知道为什么调用dijkstra()函数之后 ...
- POJ1797 Heavy Transportation 【Dijkstra】
Heavy Transportation Time Limit: 3000MS Memory Limit: 30000K Total Submissions: 21037 Accepted: ...
- HDU 4370 0 or 1 (01规划)【Dijkstra】||【spfa】
<题目链接> 题目大意: 一个n*n的01矩阵,满足以下条件 1.X12+X13+...X1n=12.X1n+X2n+...Xn-1n=13.for each i (1<i<n ...
- hdu 3499 flight 【分层图】+【Dijkstra】
<题目链接> 题目大意: 现在给你一些点,这些点之间存在一些有向边,每条边都有对应的边权,有一次机会能够使某条边的边权变为原来的1/2,求从起点到终点的最短距离. 解题分析: 分层图最短路 ...
- poj 2502 Subway【Dijkstra】
<题目链接> 题目大意: 某学生从家到学校之间有N(<200)条地铁,这个学生可以在任意站点上下车,无论何时都能赶上地铁,可以从一条地铁的任意一站到另一条地跌的任意一站,学生步行速度 ...
- POJ1062昂贵的聘礼(经典) 枚举区间 +【Dijkstra】
<题目链接> 昂贵的聘礼 Description 年轻的探险家来到了一个印第安部落里.在那里他和酋长的女儿相爱了,于是便向酋长去求亲.酋长要他用1000 ...
- POJ2387 Til the Cows Come Home 【Dijkstra】
题目链接:http://poj.org/problem?id=2387 题目大意; 题意:给出两个整数T,N,然后输入一些点直接的距离,求N和1之间的最短距离.. 思路:dijkstra求单源最短路, ...
- poj 1797 最大最小路段【dijkstra】 (经典)
<题目链接> 题目大意: Hugo Heavy要从城市1到城市N运送货物,有M条道路,每条道路都有它的最大载重量,问从城市1到城市N运送最多的重量是多少. 解题分析: 感觉这道题用dijk ...
随机推荐
- AFNetWorking3.0使用 自签名证书的https请求
前几日,项目组出于安全角度的考虑,要求项目中的请求使用https请求,因为是企业内部使用的app,因此使用了自签名的证书,而自签名的证书是不受信任的,所以我们就需要自己来做证书的验证,包括服务器验证客 ...
- C#自定义控件背景色透明的方法
I struggled for ages with the problem of having controls show through a control that was painted on ...
- php 扩展 redis
1.通过phpinfo 查看php的版本( 要注意php 是nts 还是ts 通过phpinfo(); 查看其中的 Thread Safety 项,这个项目就是查看是否是线程安全,如果是:enabl ...
- Uva592 Island of Logic
题意:神人鬼三个种族,神只说真话,鬼只说假话,人白天说真话,晚上说假话.根据对话内容区分种族和白天黑夜. 最多有A, B, C, D, E五个人 算法:枚举A, B, C, D, E的种族情况和 ...
- WPF仿360卫士9.0界面设计
Chrome插件——一键保存网页为PDF1.0 http://blog.csdn.net/bdstjk/article/details/9208313 仿照网上的一个代码写的,地址找不到了. 将窗体, ...
- 怎样解决VirtrualBox不能新建64bit的系统的问题
假设你的VirtrualBox不能新建64bit的虚拟机一般有以下两个原因: 1.电脑是32位的,不支持创建64bit的虚拟机 2.电脑不支持Intel VT-x,或者是Intel VT-x没有打开 ...
- Android Studio开发JNIproject
使用Android Sutdio创建一个新的project后,接下来记录创建NDKproject的基本步骤. 本文将达到: 1. 创建NDKproject 2. 在JNI中输出Log语句 3. 指定编 ...
- Codeforces Educational Codeforces Round 3 C. Load Balancing 贪心
C. Load Balancing 题目连接: http://www.codeforces.com/contest/609/problem/C Description In the school co ...
- This implementation is not part of the Windows Platform FIPS validated cryptographic algorithms. 此实现不是 Windows 平台 FIPS 验证的加密算法的一部分 解决方案
但web启用了md5加密后 有可能出现这样的错误 This implementation is not part of the Windows Platform FIPS validated cryp ...
- hdu5072 2014 Asia AnShan Regional Contest C Coprime
最后一次参加亚洲区…… 题意:给出n(3 ≤ n ≤ 105)个数字,每个数ai满足1 ≤ ai ≤ 105,求有多少对(a,b,c)满足[(a, b) = (b, c) = (a, c) = 1] ...