堆优化的Dijkstra算法
迪杰斯特拉算法(Dijkstra)是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法。是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题。迪杰斯特拉算法主要特点是从起始点开始,采用贪心算法的策略,每次遍历到始点距离最近且未访问过的顶点的邻接节点,直到扩展到终点为止。
这里的Dijkstra算法是经过堆优化的算法,用于解决稀疏图问题。
基本思想是通过邻接表储存每个点所能到达的点。用一个dist[]数组来储存初始点到达每个节点的最短距离,并初始化为无穷大。首先将初始点推入队列中,然后通过这个点来遍历每一个子节点并将每个使得初始节点到当前点的距离加上这个点到每个子节点的距离小于当前dist[]的值替换掉,并推入队列中,由于这里是小根堆,所取到的队首的值一定是当初始节点距离的点并开始下一轮遍历,以此类推直至找到目标节点的最短距离。
代码:
#include<iostream> #include<cstring> #include<algorithm> #include<queue> using namespace std; typedef pair<int,int> PII; const int N=200010; int ne[N],h[N],e[N],idx;//邻接表储存方式 int n,m; int w[N],dist[N];//w储存每条边的权值,dist储存初始节点到每一个节点的最短距离 bool st[N];//储存每个点是否找到了最短距离 priority_queue<PII,vector<PII>,greater<PII>> heap;//小根堆的定义 void insert(int a,int b,int c) { e[idx]=b; w[idx]=c;//储存权值 ne[idx]=h[a]; h[a]=idx++; } int dijkstra() { memset(dist,0x3f,sizeof dist);//将距离初始初始化为正无穷 heap.push({0,1});//将初始节点推入队列中 while(!heap.empty()) { auto t=heap.top(); heap.pop(); int cnt=t.second,distance=t.first;//t.first代表当前节点到初始节点的最短距离,second代表当前是哪一个节点 if(st[cnt]) continue; st[cnt]=true; for(int i=h[cnt];i!=-1;i=ne[i])//遍历这个链表 { int j=e[i]; if(dist[j]>distance+w[i])//如果当前节点到子节点的距离加上这条边的权值小于之前头结点到子节点的距离 { dist[j]=distance+w[i]; heap.push({dist[j],j}); } } } if(dist[n]!=0x3f3f3f3f) return dist[n]; return -1; } int main() { scanf("%d%d",&n,&m); memset(h,-1,sizeof h); while(m--) { int a,b,c; scanf("%d%d%d",&a,&b,&c); insert(a,b,c); } printf("%d",dijkstra()); return 0; }