阅读 111

Dijkstra最短路算法

Dijkstra算法

Dijkstra算法也是解决单源最短路问题的算法,他的算法利用了贪心的思想,不能有负边权。

算法步骤

  1. 首先将与起点s相连的结点全部放入集合中,找出距离最小的一个结点u,那么u就是第一个确定最短路径的结点。从s到u的路径肯定是最短的,因为s绕道别的地方在到u必然更远。
  2. 然后将继续取出集合中距离s最短的结点u,再将与u相连的结点放入集合。
  3. 继续以上的操作,在每一次迭代过程中都能确定一个结点的最短路径。

算法分析

  1. 图存储问题:使用链式前向星存储,防止图过大空间不够。

  2. 如何在每次迭代时快速找到集合中距离最小的结点:利用小根堆的数据结构来处理,每次的堆顶元素就是集合中最小的结点,这里我使用C++的STL中的priority_queue<>优先队列,切记如果找到最小结点必须要标记当前结点已是最短距离,后面不需要再访问。

  3. 时间复杂度:O(mlog2(n))

代码

typedef pair<int,int> PII;//相当于一个结构体:first表示最短距离,second表示结点编号 
int d[N];
int e[N],ne[N],w[N],idx;//e[i]位置i的边所指向的结点 ne[i]位置i所指向的下一个位置 w[i]位置i的边的权值 
int h[N];//h[u]表示与结点u连接的第一条边的位置 
int b;//起点
bool vis[N];//表示结点i的最短路是否已找到。 
void init()
{
    memset(d,0x3f,sizeof d);//初始化初始距离为无限大 
	memset(h,-1,sizeof h);//初始化h所指向的位置为-1
}
void add(int a,int b,int c)//往图中添加边和结点 
{
	e[idx]=b;
	w[idx]=c;
	ne[idx]=h[a];
	h[a]=idx++;
}
void Dijkstra() 
{
	priority_queue<PII,vector<PII>,greater<PII> > heap;
	heap.push({0,b});
	d[b]=0;
	while(!heap.empty())
	{
		auto t=heap.top();heap.pop();//取出集合中距离最小的结点,然后删除 
		int from=t.second,mind=t.first;
		if(vis[from]) continue;//如果以使用过不在使用 
		vis[from]=1;//设置结点from已经使用过 
		for(int i=h[from];~i;i=ne[i])//遍历以from为起点的边 
		{
			int to=e[i];
			if(d[to]>d[from]+w[i])
			{
				d[to]=d[from]+w[i];
				heap.push({d[to],to}); 
			}
		}
	}	 
}
复制代码
文章分类
后端
文章标签