原理
实际为贪心算法,结点分为两个集合,已确定最短路径的点集合S和未确定最短路径的点集合T,使用
D
u
D_{u}
Du表示从起点s到终点u的最短路径
算法
- 初始化集合S为空,集合T包含所有的顶点,同时初始化 D s = 0 D_{s}=0 Ds=0,其它点的距离 D u = + ∞ D_{u}=+\infty Du=+∞
- 从集合T中取最短路径最小的点u加入到集合S中
- 对与顶点u的相邻的顶点作松驰操作
- 重复2直到集合T为空
n为顶点数,m为边数
求最小的点可以使用下面几种方法
优先级队列
在从最短路径 最小的点中选取最小值,可以使用优先级队列。因为在松驰操作中,会将有更新的顶点及其对应的距离信息作为数据放入队列,存在对于同一顶点,可能会多次入优先级队列,需要在从队列中取出信息时,需要判断顶点是否在S集合中,如果在,则忽略
时间复杂度
O
(
(
n
+
m
)
log
n
)
O((n+m)\log n)
O((n+m)logn)
在判断状态空间中的点是否已经处理过,可以判断队列中的点距离与当前点u对应的距离d[u]是否一致,如果不一致,说明已经计算过,则不处理
暴力法
使用bool vis[N]数组来表示区分 S,T集合。用vis[i]=true来表示属于S集合,为false的表示T集合
时间复杂度
O
(
(
n
2
+
m
)
)
O((n^2+m))
O((n2+m))
int minu = -1;
for (int i = 0; i < N; i++) {
if (!vis[i] && (minu == -1 || d[i] < d[minu]) {
minu = i;
}
}
实现
#include <bits/stdc++.h>
using namespace std;
#define _for(i, a, b) for(int i = (a); i < (b); i++)
#define _rep(i, a, b) for (int i = (a); i <= (b); i++)
struct Edge
{
int u, v, d;
};
struct HeapNode
{
int u, d;
bool operator<(const HeapNode& other) const
{
return d > other.d;
}
};
template <int SZV, int INF>
struct Dijkstra
{
int n;
vector<Edge> edges;
vector<int> graph[SZV];
bool done[SZV];
int d[SZV], p[SZV];
void init(int n)
{
this->n = n;
edges.clear();
_for(i, 0, n) {
graph[i].clear();
}
}
void addEdge(int u, int v, int d)
{
graph[u].push_back(edges.size());
edges.push_back({u, v, d});
}
void dijkstra(int s)
{
priority_queue<HeapNode> pq;
fill_n(done, n, false);
fill_n(d, n, INF);
d[s] = 0;
pq.push({s, 0});
while (!pq.empty()) {
HeapNode curNode = pq.top();
pq.pop();
int u = curNode.u;
if (done[u]) {
continue;
}
done[u] = true;
_for(i, 0, graph[u].size()) {
const auto& edge = edges[graph[u][i]];
int v = edge.v;
if (d[u] + edge.d < d[v]) {
d[v] = d[u] + edge.d;
p[v] = graph[u][i];
pq.push({v, d[v]});
}
}
}
}
void getPath(int s, int e, deque<int>& path, bool rev = false)
{
int x = e;
if (rev) {
path.push_back(x);
} else {
path.push_front(x);
}
while (x != s) {
x = edges[p[x]].u;
if (rev) {
path.push_back(x);
} else {
path.push_front(x);
}
}
}
};
实践
UVa11374 Airport Express
UVa1416 Warfare And Logistics
UVa10537 The Toll! Revisited
UVa658 It’s not a Bug, it’s a Feature!