【算法】Dijkstra算法
前言
已经有一段时间没有更新博客了,主要是因为变得比较忙了,什么高数啊大物啊期中考试都来了,也就没时间写代码了。最近还参加了一个大创的项目,也在忙着修改着项目申报表。
现在我可是深刻感受到了:专业选得好,年年赛高考啊。
今天来写一下Dijkstra算法,可是想到还有之前的Prim算法,关键路径算法,Kruskal算法还有后面的平衡排序树,B树的修复,哎呀我滴娘嘞,怎么能这么多嘞!

算法思想
Dijkstra算法主要用于图中求一个固定点到其余各个顶点的最短路径。
算法需要引入几个辅助数组。
- \(S\):表示已经找到最短路径的顶点的集合
- $dist$:辅助数组,$dist[i]$表示目前已找到的从开始点$v_{0}$到终点$v_{i}$的当前最短路径
- $path$:$path[i]$表示从$v_{0}$到$v_{i}$的最短路径需要经过依次经过的结点。
大概的步骤如下:
- 初始化,加入以$1$为开始点,则$dist[i]$初始化为从$v_{1}$到$v_{i}$的路径长度(权值)
- 从$dist$中找出距离最短的,将其加入$S$
- 修正从$v_{0}$出发到顶点集合$V-S$($V$表示全集)上任意顶点的路径长度。
- 重复上述过程,即可求出按最短路径长度递增顺序排列的数组$S$.
其中修正过程如下:
- 从$v_{0}$出发,到集合$V-S$上任一顶点$v_{i}$的当前最短路径长度为$dist[i]$
- 从$v_{0}$出发,中间经过了新加入S中的顶点$v_{k}$,然后到达集合$V-S$上任一顶点$v_{i}$路径长度为$dist[k]+g.arcs[k][j]$.如果$dist[k]+g.arcs[k][j] < dist[i]$,则$dist[i] = dist[k]+g.arcs[k][j]$
实现
关键代码
void Graph::dijkstra()
{
for ( int i = 2; i <= vernum - 1; i++)
{
int min = 32767, k;
for ( int j = 1; j < vernum; j++)
{
if (!dist[j].hasFound && dist[j].data < min)
{
k = j;
min = dist[j].data;
}
}
if (min == 32767)
{
return ;
}
dist[k].hasFound = true ;
for ( int j = 0; j < vernum; j++)
{
if (!dist[j].hasFound && arc[k][j] != 32767 && dist[k].data + arc[k][j] < dist[j].data)
{
dist[j].data = dist[k].data + arc[k][j];
}
}
}
}
具体过程在算法思路里已经详尽得给出,不过这里并没有用到path。
解题
下面为NOJ第22题的代码,这里使用一个$bool$值来判定是否在$S$中。
/*
* @Author: zh(RickSchanze)(帝皇の惊)
* @Description: Dijkstra算法
* @Date: 2022-05-09 23:14:54
* @LastEditTime: 2022-05-14 20:12:37
*/
#include
#include
struct Isfound
{
int data = 32767;
bool hasFound = false ;
};
struct Graph
{
int vertex[100] = {0};
int arc[100][100];
int vernum = 0;
int arcnum = 0;
Isfound dist[100];
void createGraph();
void dijkstra();
void print();
};
void Graph::print()
{
struct temp
{
int index;
int data;
};
temp t[100];
for ( int i = 2; i <= vernum; i++)
{
t[i].index = i;
t[i].data = dist[i].data;
}
std::sort(&t[2], &t[vernum], [](temp a, temp b)
{ return a.data < b.data; });
for ( int i = 2; i <= vernum; i++)
{
if (t[i].data == 32767)
{
std::cout << "1"
<< " " << t[i].index << " "
<< "-1" << std::endl;
continue ;
}
std::cout << "1"
<< " " << t[i].index
<< " " << t[i].data << std::endl;
}
}
void Graph::createGraph()
{
std::cin >> vernum >> arcnum;
for ( int i = 1; i <= vernum; i++)
{
vertex[i] = i;
}
for ( int i = 1; i <= arcnum; i++)
{
for ( int j = 1; j <= arcnum; j++)
{
arc[i][j] = 32767;
}
}
for ( int i = 0; i < arcnum; i++)
{
int first, end;
std::cin >> first >> end;
std::cin >> arc[first][end];
}
for ( int i = 2; i <= vernum; i++)
{
dist[i].data = arc[1][i];
}
}
void Graph::dijkstra()
{
for ( int i = 2; i <= vernum - 1; i++)
{
int min = 32767, k;
for ( int j = 1; j < vernum; j++)
{
if (!dist[j].hasFound && dist[j].data < min)
{
k = j;
min = dist[j].data;
}
}
if (min == 32767)
{
return ;
}
dist[k].hasFound = true ;
for ( int j = 0; j < vernum; j++)
{
if (!dist[j].hasFound && arc[k][j] != 32767 && dist[k].data + arc[k][j] < dist[j].data)
{
dist[j].data = dist[k].data + arc[k][j];
}
}
}
}
int main()
{
Graph aGraph;
aGraph.createGraph();
aGraph.dijkstra();
aGraph.print();
return 0;
}

浙公网安备 33010602011771号