0
点赞
收藏
分享

微信扫一扫

堆优化版Dijkstra算法思路

洒在心头的阳光 2022-02-13 阅读 69
算法

注意:Dijkstra算法只适用于边权为非负值的带权图

时间复杂度为O(m*log n)级别

主要思路:(采用STL中的优先队列进行优化)

准备工作:先用vector容器开适当大小的数组存放与每个点相连点的位置与边权(用pair类型成对存放),创建dis[N]来存放所有点到起始点的距离,并将所有点到起始点的距离初始化为INF(int范围内最大的数),以便后续更新最短距离。创建vis[N]来标记某个点是否被更新过。

将某点的编号和该点当前到起始点最短距离存入队列(假设点1为起始点,点1到1的最短距离为0,那么将存入(1,0)),当队列不为空时选出堆顶元素(以下操作一直循环到队列为空),用该点(假设为点u)的位置带入vector容器遍历与点u相连的点(假设为点v),如果dis[v]>dis[u]+边u-v的边权(用w表示),就将dis[v]更新为dis[u]+w;最后再把(v,dis[v])存入队列即可。

完整代码如下:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5;
const int INF=1e9;
int dis[N];
bool vis[N];
vector <pair<int,int> >g[N];
struct note{
	int id;//点的位置
	int d;//该点到起始点的最短距离
};
bool operator<(note a,note b){//重载小于号运算符,让堆元素从小到大排列
	return a.d>b.d; 
}
priority_queue<note> que;
int n,m,u,v,w;

Dijkstra(int st){
	for(int i=1;i<=n;i++){
	    vis[i]=0,dis[i]=INF;//初始化
	} 
	dis[st]=0;
	que.push({st,0});
	while(!que.empty()){
		note t=que.top();que.pop();//每次取出堆顶元素后弹出该元素
		int u=t.id;
		if(vis[u]) continue;//如果已经被更新过就跳过该点
		vis[u]=1;
		for(auto eg:g[u]){//遍历与点u相邻的所有点
			int v=eg.first;
			int w=eg.second;
			if(dis[v]>dis[u]+w) dis[v]=dis[u]+w;
			que.push({v,dis[v]});
		}
	}
}

int main(){
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		cin>>u>>v>>w;
		g[u].push_back({v,w});
	}
	int st;cin>>st;
    Dijkstra(st);
    for(int i=1;i<=n;i++){
    	cout<<st<<"->"<<i<<" shortest path is"<<dis[i]<<endl;
	}
    return 0;
}
举报

相关推荐

0 条评论