dijkstra堆优化 详解(洛谷模板题)

本文详细介绍了一种稳定且高效的单源最短路径算法——Dijkstra算法。通过逐步解析算法流程及其实现代码,帮助读者理解算法的基本原理和操作细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


一、算法概况

 dijkstra是一种稳定的求单源最短路的算法,时间复杂度O((m+n)logn)  ,m表示边数,n表示点数。

二、算法过程

1.将源点以及和他相连的点加入堆
2.选出堆顶元素A(代价最小的元素),将他从堆中删除,然后调整堆
3. 处理与u相邻的,未被访问过的,满足三角不等式的顶点
    1):若该点在堆里,更新距离,并调整该元素在堆中的位置。
    2):若该点不在堆里,加入堆,更新堆。
4. 若取到的A为终点,结束算法;否则重复步骤2、3。
(转自百度百科)

三、代码实现

void dij(int A)
{
	q.push(make_pair(0,A));//将源点的距离和源点加入堆
	for(int i=1;i<=n;i++){
		dis[i]=inf;//先将每个点的初始化
	}
	dis[A]=0;//源点到源点的距离是0
	while(!q.empty()){//如果堆不为空,即并不是所有与源点联通的点都被遍历到了,我们就continue
		int now=q.top().second;//取出当前堆顶的点
		q.pop();//弹出堆顶元素
		if(vis[now]) continue;//如果被访问过,我们就跳过
		vis[now]=1;//打标记
		for(int i=head[now];i;i=e[i].next){//遍历与now直接相连的点
			if(dis[now]+e[i].len<dis[e[i].to]){//如果满足三角形不等式
				dis[e[i].to]=dis[now]+e[i].len;//更新该点的最短路
				q.push(make_pair(dis[e[i].to],e[i].to));//讲我们更新的点加入堆
			}
		}
	}
}

四、总代码

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<vector>
const int maxn=1e6+7;
const int inf=1e9+7;
using namespace std;
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > q;
struct node{
	int len,to,next;
}e[maxn];
int n,m,s,from,go,val,size=0,head[maxn],dis[maxn];
bool vis[maxn];
void addedge(int from,int go,int val){
	size++;
	e[size].to=go;
	e[size].len=val;
	e[size].next=head[from];
	head[from]=size;
}
void dij(int A)
{
	q.push(make_pair(0,A));
	for(int i=1;i<=n;i++){
		dis[i]=inf;
	}
	dis[A]=0;
	while(!q.empty()){
		int now=q.top().second;
		q.pop();
		if(vis[now]) continue;
		vis[now]=1;
		for(int i=head[now];i;i=e[i].next){
			if(dis[now]+e[i].len<dis[e[i].to]){
				dis[e[i].to]=dis[now]+e[i].len;
				q.push(make_pair(dis[e[i].to],e[i].to));
			}
		}
	}
}
int main()
{
	scanf("%d%d%d",&n,&m,&s);
	for(int i=1;i<=m;i++){
		scanf("%d%d%d",&from,&go,&val);
		addedge(from,go,val);
	}
	dij(s);
	for(int i=1;i<=n;i++){
		if(dis[i]==inf){
			printf("2147483647 ");
		}
		else{
			printf("%d ",dis[i]);
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值