Dijkstra的算法原理:
Dijkstra算法采用贪心策略,逐步找到从起点到其它顶点的最短路径,Dijkstra可以计算有向图和无向图最短路径,并且可以处理负权边。。算法的基本思想是:每次从未访问的顶点中选择一个距离起点最近的顶点,然后更新该顶点到其它顶点的距离。重复这个过程,直到所有顶点都被访问过。(本来是不想再赘述的,既然是写给小白看的,还是决定再写一下)。
Dijkstra算法的适用条件
Dijkstra常用于解决单源最短路径问题,朴素解法的速度较慢,对于很多的题目而言,都是要进行优化的。
详细讲解过程
详细的讲解过程可以看(感觉图形和文字讲解可能不便于理解,还是看视频讲解来的更快一些)
此处不再进行赘述。
朴素解法完整代码o(n2)
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
int graph[2505][2505];//邻接矩阵
int dis[2505];//最短路
int check[2505];//标记数组,是否访问过
int main(){
memset(dis,INF,sizeof(dis));
int n,m,s,t;//n个点m个边 ,起始点s,终止点t
cin>>n>>m>>s>>t;
for(int i=1;i<=m;i++){
int u,v,w;
cin>>u>>v>>w;
graph[u][v]=graph[v][u]=w;//无向图赋值
}
dis[s]=0;//起始点到起始点距离为0
//开始进行Dijkstra
for(int i=1;i<=n;i++){//遍历n个点
int minn=INF;
int minx;
for(int j=1;j<=n;j++){
if(dis[j]<minn&&check[j]==0){//这个点的路径小于minn并且没有被标记过
minn=dis[j];
minx=j;//记录该节点
}
}
check[minx]=1;
for(int j=1;j<=n;j++){
if(graph[minx][j]>0){//该点到其他个点的距离
if(minn+graph[minx][j]<dis[j]){//绕路走小于正常走
dis[j]=minn+graph[minx][j];
}
}
}
}
cout<<dis[t];//输出起始点到终止点的最小路径
return 0;
}
朴素解法感觉几乎用不到,一般都是要进行堆优化的。
堆优化完整代码O(mlogn)
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
const int INF = 0x3f3f3f3f;
struct Edge {
int to; // 目标顶点
int weight; // 边的权重
};
vector<Edge> edge[N]; // 边集合,存储图的边信息
int dis[N]; // 存储最短路径长度
int check[N]; // 标记数组,标记顶点是否已经被访问过
struct node {
int v, dist;
bool operator>(const node x) const {
return dist > x.dist;
}
};//小根堆模版
void dijkstra(int n, int s) {
/*fill是STL库中的一个算法,能设置任意类型的值,而memset只能设置单个字节的值,
当memset不是很好用时,不妨试试fill
*/
fill(dis, dis + n + 1, INF); // 初始化最短路径长度为无穷大
dis[s] = 0; // 起始顶点到自身的距禿为0
priority_queue<node, vector<node>, greater<node> > pq; // 小顶堆,存储顶点和距离信息
pq.push({s, 0}); // 将起始顶点加入堆中
while (!pq.empty()) {
node current = pq.top(); // 获取当前最短的顶点
pq.pop();
int u = current.v; // 当前顶点
if (check[u] == 1) continue; // 如果当前顶点已经被访问过,则跳过
check[u] = 1; // 标记当前顶点为已访问
for (int i = 0; i < edge[u].size(); i++) {
int v = edge[u][i].to; // 目标顶点
int w = edge[u][i].weight; // 边的权重
if (dis[u] + w < dis[v]) { // 如果通过当前顶点到达目标顶点的距禿更短
dis[v] = dis[u] + w; // 更新最短路径长度
pq.push({v, dis[v]}); // 将目标顶点加入堆中
}
}
}
}
int main() {
int n, m, s;
cin >> n >> m >> s; // 输入顶点数、边数、起始顶点
for (int i = 1; i <= m; i++) {
int u, v, w;
cin >> u >> v >> w; // 输入边的起始顶点、目标顶点和权重
edge[u].push_back({v, w}); // 添加边到边集合
}
dijkstra(n, s); // 运行Dijkstra算法
for (int i = 1; i <= n; i++) {
cout << dis[i] << " "; // 输出最短路径长度
}
return 0;
}
例题:P4779 【模板】单源最短路径(标准版) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
文章如有问题,欢迎指正。