定义


Dijkstra 算法

由荷兰计算机科学家 E. W. Dijkstra 于 1956 年发现,1959 年公开发表的一种用于求解非负权图上单源最短路径的算法。

过程


设起点为,结点集合为,边集为
同时设数组为到点的距离,分别为已经确定最短路径和未确定最短路径的点集。

  1. 初始化:,其余。令
  2. 选点:遍历,求出其中最小的结点
  3. 松弛:遍历的出边以及对应的结点,如果的距离加上出边的距离是否小于的距离,则更新。即
  4. 重复:将移到中,若不为空,重复2和3。

实现


朴素实现

struct edge
{
	int v, w;
};
 
int N;
int n, m;
vector<edge> p[N];
int d[N], 
bool vis[N];
 
void dijkstra(int s)
{
	// 初始化
	std::fill(dist, dist + N, 1e9);
	dis[s] = 0;
	
	for(int i = 1; i <= n; i++)
	{
		// 选点
		int u = -1;
		for(int j = 1; j <= n; j++)
			if(!vis[j] && (u == -1 || d[j] < d[u]))
				u = j;
		
		vis[u] = true;
		
		// 松弛
		for(auto &edge : p[u])
		{
			int v = edge.v;
			int w = edge.w;
			if(d[u] + w < d[v])
				d[v] = d[u] + w;
		}
	}
}
 

优先队列实现

利用优先队列,可以将取点操作的复杂度从降为

struct edge
{
	int v, w;
};
 
struct node
{
	int u, d;
	
	bool operator>(const node& a) const
	{
		return d < a.d;
	}
}
 
int N;
int n, m;
vector<edge> p[N];
int d[N], 
bool vis[N];
priority_queue<node, vector<node>, greater<node>> pq;
 
void dijkstra(int s)
{
	// 初始化
	std::fill(dist, dist + N, 1e9);
	dis[s] = 0;
	pq.push({s, 0});
	
	while(pq.empty())
	{
		// 选点
		int u = pq.top().u;
		pq.pop();
		
		// 已经确定的点直接跳过
		if(vis[u] == true)
			continue;
		vis[u] = true;
		
		// 松弛
		for(auto &edge : p[u])
		{
			int v = edge.v;
			int w = edge.w;
			if(d[u] + w < d[v])
			{
				d[v] = d[u] + w;
				pq.push({v, d[v]});
			}
			
		}
	}
}