头像

欢迎来到我的博客

分享题解与总结

P3371 单源最短路径

模版:

看了几个版本的dijkstra,最终以如下代码作为板子。

看如下代码之前,你需要先学这两位大佬的课程

https://www.bilibili.com/video/BV1Ya411L7gb/?spm_id_from=333.1387.collection.video_card.click&vd_source=34da0aa07edaca8b889ad016b25904d0

https://www.bilibili.com/video/BV14dXpYEEZS/?spm_id_from=333.337.search-card.all.click&vd_source=34da0aa07edaca8b889ad016b25904d0

前提: D=<V,E>且w_i>=0

优化:if(dis>d[u1]) continue;

合法性

  1. d[v1] = d[u1] + w1 实时更新为更小值
  2. pq.push({d[v1], v1}) 压入新的(更小的)距离
  3. 堆中关于 v1 的条目:旧的(大)vs 新的(小)
  4. 最小堆保证:小的先弹出,大的后弹出
  5. 先弹出的:dis == d[v1](当前最小)→ 处理
    后弹出的:dis > d[v1](已过时) → 跳过

断言:弹出的一定只可能是dis>=d[u1].

反证:假设弹出 (dis, u)dis < d[u].

  • d[u] 是当前已知最短距离
  • dis < d[u] 意味着存在更短路径
  • Dijkstra 性质:第一次弹出时 d[u] 已确定,不可能有更短的
  • 矛盾!

模版:

#include<bits/stdc++.h>
#define N 10005
#define INF LLONG_MAX
using namespace std;
using ll=long long;
struct edge{ll v,w;};
vector<edge> e[N]; 
priority_queue<pair<ll,ll>,vector<pair<ll,ll>>,greater<pair<ll,ll>>> pq;
ll d[N];//,vis[N];
ll n,m,s,u0,v0,w0;

void dijkstra()
{
	for(ll i=1;i<=n;++i) d[i]=INF;
	d[s]=0;
	
	pq.push({0,s});
	while(!pq.empty()){
		auto head=pq.top(); pq.pop();
		ll u1=head.second,d1=head.first;
		if(d1>d[u1]) continue;
		
		for(auto ed:e[u1]){
			ll v1=ed.v,w1=ed.w;
			if(d[u1]+w1<d[v1]){
				d[v1]=d[u1]+w1;
				pq.push({d[v1],v1});
			}
		}
	}
}

int main()
{
	cin>>n>>m>>s;
	for(ll i=1;i<=m;++i){
		cin>>u0>>v0>>w0;
		e[u0].push_back({v0,w0});	
	}
	dijkstra();
	for(ll i=1;i<=n;++i){
		if(d[i]==LLONG_MAX) d[i]=INT_MAX;
		cout<<d[i]<<" ";
	}
	return 0;
}
posted @ 2026-02-24 09:55  king_steph1209  阅读(13)  评论(0)    收藏  举报