主要分为五部分
算法思想:每次选出dis最小的那个点i,则dis[i]必定为为顶点s到顶点i的最短距离
更新所有与i相邻的顶点的dis值
依据:如果存在一条i到j的最短路径,其经过的节点为(i……k,j)。那么(i……k)的这条路径也必然是i到k的最短路径。
每个版本的最初都是构建图,首先将图初始化,然后进行加边。对于双向图要注意双向加边。最后进行dijkstra算法,详情请看主函数。
dijkstra算法伪代码:
清除所有点的标记
设dis[s] = 0;其它d[i]为无穷大
循环N次
{
在所有未标记结点中,选出dis值最小的节点x;
给结点x标记
对所有从x出发的边(x,y)进行更新
}
本文注意要点:所有版本接口相同,节点编号均从0开始。
/***************************
//邻接矩阵版dijkstra算法
***************************/
#define INF 0x3F3F3F3F //把INF(最大值)设置成0x3f3f3f3f
const int MAXN = 1010; //所开数组大小可以修改,一般情况1010足够
int G[MAXN][MAXN]; //G[a][b]表示a,b的权值,G[][]二维数组为构建的邻接矩阵
int vis[MAXN]; //vis[a]记录是否已经查看过'a'点vis[a] == 1 表示已经查看过改点
int dis[MAXN]; //dis[a]记录从起点到'a'点之间的最短路径
//初始化函数,应该在加第一条边之前进行初始化
void init(int n){//n表示gongyoun个点
for(int i=0;i
这样邻接矩阵版的dij就结束了。不仅包含了dij的算法内涵还有邻接矩阵的相关知识。
此处当然应该是上面的几个函数到底怎么用,让我们再贴代码,此处给出杭电oj1874 题解答,下为题目连接:
http://acm.hdu.edu.cn/showproblem.php?pid=1874
#include //此处头文件几乎包含常见文件,可各取所需
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
这道题的解答是一个纯粹的最短路径的题,很适合熟悉dlj算法。
下面给出其他三种更高效的模板:/*上面已经清晰的不再赘述*/
/****************************
//普通邻接表版dijkstra算法
****************************/
//对于邻接表的方法主要的就是如何用邻接表存图,此处不再赘述,可百度各种资料
#define INF 0x3F3F3F3F
const int MAXN_EDGE = 200010;
const int MAXN_NODE = 100010;
int Next[MAXN_EDGE], head[MAXN_NODE],To[MAXN] ,G[MAXN_EDGE], w[MAXN_EDGE];
int tot;
void init(int n){
tot = 0;
for(int i = 0; i < n; i++){
head[i] = -1;
}
}
void add_edge(int u,int v,int d){
w[tot] = d;
To[tot] = v;
Next[tot] = head[u];
head[u] = tot++;
}
int vis[MAXN];
int dis[MAXN];
void dijkstra(int s,int n){
for(int i = 0;i PII;//需要用到pair
const int MAXN = 100010;//满足需求即可
vector G[MAXN];//用到vector//
//初始化
void init(int n){
for(int i=0;i
下面是vector版的dij复杂度基本上也是O(n*n)
/************************
//vector版dijkstra算法
************************/
//对于vector版本
#define INF 0x3FFFFFFF
typedef pair PII;//需要用到pair
const int MAXN = 100010;//满足需求即可
vector G[MAXN];//用到vector//
//初始化
void init(int n){
for(int i=0;i
下面是优先队列版dij。时间复杂度得到优化为哦O(n*log(n))
/**************************
//优先队列版dijkstra算法
**************************/
//优先队列对dij算法进行了优化降低了算法复杂度
//一般推荐使用此种方法
#define INF 0x3FFFFFFF
#define PB(X) push_back(X)
#define MP(X,Y) make_pair(X,Y)
typedef pairPII;
typedef vectorVII;
const int MAXN = 100010;
vector G[MAXN];
void add_edge(int u,int v,int d){
G[u].PB(MP(v,d));
}
void init(int n){
for(int i=0;i >q;//声明优先队列:每次从队列中取出的是具有最高优先权的元素。
//优先队列第一个参数为比较类型,第二个为容器类型,第三个为比较函数。
//greater实现小顶堆//less 实现大顶堆(默认为大顶堆)
q.push(MP(dis[s],s));//将他本身先推进优先队列
while(!q.empty()){//当队列空时已将所有边加入队列并推出
PII p = q.top();
int x = p.second;
q.pop();
if(vis[x])continue;
vis[x] = 1;
for(int i=0;i
到这里4中不同的算法实现就讲完了,主要的就是看懂代码,最好自己是实现一遍。其中邻接矩阵和邻接表最容易体现dijkstra的精髓。谢谢。