迪杰斯特拉(Dijkstra)算法
迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径。它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止。
基本思想
通过Dijkstra计算图G中的最短路径时,需要指定起点s(即从顶点s开始计算)。
此外,引进两个集合S和U。S的作用是记录已求出最短路径的顶点(以及相应的最短路径长度),而U则是记录还未求出最短路径的顶点(以及该顶点到起点s的距离)。
初始时,S中只有起点s;U中是除s之外的顶点,并且U中顶点的路径是"起点s到该顶点的路径"。然后,从U中找出路径最短的顶点,并将其加入到S中;接着,更新U中的顶点和顶点对应的路径。 然后,再从U中找出路径最短的顶点,并将其加入到S中;接着,更新U中的顶点和顶点对应的路径。 ... 重复该操作,直到遍历完所有顶点。
核心思想
更新估算距离,松弛
算法图解
https://www.cnblogs.com/skywang12345/p/3711512.html
堆实现
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;
const int Ni = 10000;
const int INF = 1 << 27;
struct node
{
int point, value;
// 构造
node(int a, int b)
{
point = a;
value = b;
}
// 重载<操作符
bool operator<(const node &a) const
{
// 对小于运算符进行重载,如果两个值相等,那么继续判断point,如果不等,则返回false
if (value == a.value)
{
return point < a.point;
}
else
{
return value > a.value;
}
}
};
vector<node> e[Ni];
int dis[Ni], n;
priority_queue<node> q;
void dijkstra();
int main()
{
int a, b, c, m;
scanf("%d%d", &n, &m);
while (m--)
{
scanf("%d%d%d", &a, &b, &c);
e[a].push_back(node(b, c));
e[b].push_back(node(a, c));
}
// for (int i = 0; i <= n; i++)
// {
// dis[i] = INF;
// }
memset(dis, 0x3f, sizeof(dis));
dis[1] = 0;
// 优先队列,队头元素最大,但是如果类型为struct需要重载<运算符
q.push(node(1, dis[1]));
dijkstra();
for (int i = 1; i <= n; i++)
{
printf("%d ", dis[i]);
}
system("pause");
return 0;
}
void dijkstra()
{
while (!q.empty())
{
node x = q.top();
q.pop();
for (int i = 0; i < e[x.point].size(); i++)
{
node y = e[x.point][i];
if (dis[y.point] > dis[x.point] + y.value)
{
dis[y.point] = dis[x.point] + y.value;
q.push(node(y.point, dis[y.point]));
}
}
}
}