最短路问题之Dijkstra算法 洛谷 单源最短路径

Dijkstra算法具体解释

Dijkstra算法用于解决单源最短路径问题,即找出从一个源节点到其他所有节点的最短路径。该算法的前提是图中不能有负权边,因为它基于贪心策略。Dijkstra算法的基本思想是通过逐步确定到达每个节点的最短路径长度来求解问题。其主要步骤如下:

  1. 初始化:将源点到各个顶点的距离初始化为无穷大,源点的距离初始化为0。

  2. 选取源点:从未被标记为已确定最短路径的节点中选择一个距离最小的节点作为当前节点。

  3. 更新距离:对于当前节点的每个邻接节点,如果通过当前节点到达该邻接节点的路径比已知路径更短,则更新该邻接节点的最短路径长度。

  4. 标记节点:将当前节点标记为已确定最短路径。

  5. 重复步骤2至4,直到所有节点都被标记为已确定最短路径,或者找到了目标节点的最短路径。

核心:贪心策略

memset(d,0x3f,sizeof d);
d[x]=0;
for(int i=1;i<n;i++){
	int u=0;
	for(int j=1;j<=n;j++){
	if(!st[j]&&d[j]<d[u]) u=j;
    }
}

核心代码,目的是为了找在经历了i次松弛操作以后里x点最近的点,只要每次都是找最近的点,最后的距离就一定是最短的,当然dj处理不了负权边

洛谷P3371 【模板】单源最短路径(弱化版)

AC code(普通版n*n)

#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int mod=2147483647; 
int n,m,s;
int u,v,w;
vector<PII> vv[100010];
long long d[10010];
int st[10010];

void dijkstra(int x){
	memset(d,0x3f,sizeof d);
	d[x]=0;
	for(int i=1;i<n;i++){
		int u=0;
		for(int j=1;j<=n;j++){
			if(!st[j]&&d[j]<d[u]) u=j;
	    }
		st[u]=1;
		for(auto ed:vv[u]){
			int a=ed.first,b=ed.second;
			if(d[a]>d[u]+b) d[a]=d[u]+b;
		}
	}
}


int main()
{
	cin>>n>>m>>s;
	for(int i=0;i<m;i++){
		cin>>u>>v>>w;
		vv[u].push_back({v,w});
	}
	dijkstra(s);
	for(int i=1;i<=n;i++){
		if(d[i]<=1e9) cout<<d[i]<<" ";
		else cout<<mod<<" ";
	}
	return 0;
} 

P4779 【模板】单源最短路径(标准版)

堆优化版

#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int mod=2147483647; 
int n,m,s;
int u,v,w;
vector<PII> vv[200010];
long long d[100010];
int st[100010];
priority_queue<PII> q;



void dijkstra(int x){
	memset(d,0x3f,sizeof d);
	d[x]=0;q.push({0,x});
	while(q.size()){
		auto t=q.top();q.pop();
		int u=t.second;
	    if(st[u]) continue; 
		st[u]=1;
		for(auto ed:vv[u]){
			int a=ed.first,b=ed.second;
			if(d[a]>d[u]+b){
				d[a]=d[u]+b;
				q.push({-d[a],a});
			}
		}
	}
}


int main()
{
	cin>>n>>m>>s;
	for(int i=0;i<m;i++){
		cin>>u>>v>>w;
		vv[u].push_back({v,w});
	}
	dijkstra(s);
	for(int i=1;i<=n;i++){
		if(d[i]<=1e9) cout<<d[i]<<" ";
		else cout<<mod<<" ";
	}
	return 0;
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值