单源最短路(dijkstra、spfa及其优化)

题目链接

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

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


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

题目描述

给定一个 n 个点,m 条有向边的带非负权图,请你计算从 s 出发,到每个点的距离。

数据保证你能从 s 出发到任意点。

输入格式

第一行为三个正整数 n,m,s。 第二行起 m 行,每行三个非负整数 ui,vi,wi ,表示从 uivi 有一条权值为 wi 的有向边。

输出格式

输出一行 n 个空格分隔的非负整数,表示 s 到每个点的距离。

输入

4 6 1 1 2 2 2 3 2 2 4 1 1 3 5 3 4 3 1 4 4

输出

0 2 4 3

说明/提示

1n105

1m2×105

s=1

1ui,vin

0wi109,0wi109

dijkstra

  • 时间复杂度:O(mlogn)
#include<bits/stdc++.h> using namespace std; const int N=1e5+10; typedef pair<int,int> pii; int n,m,s; int d[N]; vector<pii> adj[N]; priority_queue<pii,vector<pii>,greater<pii>> q; void dijkstra(int s) { memset(d,0x3f,sizeof d); d[s]=0; q.emplace(0,s); while(q.size()) { auto [t,x]=q.top(); q.pop(); if(t>d[x])continue; for(auto [y,w]:adj[x]) { if(d[y]>d[x]+w) { d[y]=d[x]+w; q.emplace(d[y],y); } } } } int main() { scanf("%d%d%d",&n,&m,&s); while(m--) { int x,y,w; scanf("%d%d%d",&x,&y,&w); adj[x].emplace_back(y,w);//注意是有向边 } dijkstra(s); for(int i=1;i<=n;i++) printf("%d ",d[i]); return 0; }

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

题面同上,不过上题使用spfa会卡~

spfa

  • 时间复杂度:(km)
  • 最坏时间复杂度:(nm)
#include<bits/stdc++.h> using namespace std; const int N=1e5+10; int n,m,s; int d[N]; bool v[N]; vector<pair<int,int>> adj[N]; queue<int> q; void spfa(int s) { memset(d,0x3f,sizeof d); d[s]=0; v[s]=true; q.push(s); while(q.size()) { int x=q.front(); q.pop(); v[x]=false; for(auto [y,w]:adj[x]) { if(d[y]>d[x]+w) { d[y]=d[x]+w; if(!v[y])v[y]=true,q.push(y); } } } } int main() { scanf("%d%d%d",&n,&m,&s); while(m--) { int x,y,w; scanf("%d%d%d",&x,&y,&w); adj[x].emplace_back(y,w);//注意是有向边 } spfa(s); for(int i=1;i<=n;i++) if(i==s)printf("0 "); else printf("%d ",d[i]==0x3f3f3f3f?INT_MAX:d[i]); return 0; }
  • SLF(入队顶点) 如果说当前点所花费的值少于当前队头点的值的话,那么我们就将这个节点插入到队头去,否则还是插入到队尾.
#include<bits/stdc++.h> using namespace std; const int N=1e4+10; int n,m,s; vector<pair<int,int>> adj[N]; bool v[N]; int d[N]; void spfa(int s) { deque<int> q; q.push_back(s); v[s]=true; memset(d,0x3f,sizeof d); d[s]=0; while(q.size()) { int x=q.front(); q.pop_front(); v[x]=false; for(auto [y,w]:adj[x]) { if(d[y]>d[x]+w) { d[y]=d[x]+w; if(q.size()&&d[y]<d[q.front()])q.push_front(y); else q.push_back(y); v[y]=true; } } } } int main() { scanf("%d%d%d",&n,&m,&s); while(m--) { int x,y,w; scanf("%d%d%d",&x,&y,&w); adj[x].emplace_back(y,w); } spfa(s); for(int i=1;i<=n;i++) printf("%d ",d[i]==0x3f3f3f3f?INT_MAX:d[i]); return 0; }
  • LLL(出队顶点)dist[q.front]num>sum ,则将 q.front 取出插入到队尾,查找下一元素,直到找到某一个 q.front 使得 dis[q.front]num<=sum ,则将 q.front 出队进行松弛操作。
#include<bits/stdc++.h> using namespace std; const int N=1e4+10; int n,m,s; vector<pair<int,int>> adj[N]; bool v[N]; int d[N]; int sum,num; void spfa(int s) { deque<int> q; q.push_back(s); v[s]=true; memset(d,0x3f,sizeof d); d[s]=0; num=1; while(q.size()) { int x=q.front(); while(num*d[x]>sum) { q.pop_front(); q.push_back(x); x=q.front(); } q.pop_front(); sum-=d[x]; num--; v[x]=false; for(auto [y,w]:adj[x]) { if(d[y]>d[x]+w) { d[y]=d[x]+w; q.push_back(y); sum+=d[y]; num++; v[y]=true; } } } } int main() { scanf("%d%d%d",&n,&m,&s); while(m--) { int x,y,w; scanf("%d%d%d",&x,&y,&w); adj[x].emplace_back(y,w); } spfa(s); for(int i=1;i<=n;i++) printf("%d ",d[i]==0x3f3f3f3f?INT_MAX:d[i]); return 0; }
  • SLF+LLL
#include<bits/stdc++.h> using namespace std; const int N=1e4+10; int n,m,s; vector<pair<int,int>> adj[N]; bool v[N]; int d[N]; int sum,num; void spfa(int s) { deque<int> q; q.push_back(s); v[s]=true; memset(d,0x3f,sizeof d); d[s]=0; num=1; while(q.size()) { int x=q.front(); while(num*d[x]>sum) { q.pop_front(); q.push_back(x); x=q.front(); } q.pop_front(); sum-=d[x]; num--; v[x]=false; for(auto [y,w]:adj[x]) { if(d[y]>d[x]+w) { d[y]=d[x]+w; if(q.size()&&d[y]<d[q.front()])q.push_front(y); else q.push_back(y); sum+=d[y]; num++; v[y]=true; } } } } int main() { scanf("%d%d%d",&n,&m,&s); while(m--) { int x,y,w; scanf("%d%d%d",&x,&y,&w); adj[x].emplace_back(y,w); } spfa(s); for(int i=1;i<=n;i++) printf("%d ",d[i]==0x3f3f3f3f?INT_MAX:d[i]); return 0; }
  • dfs优化(一般用于负环)
#include<bits/stdc++.h> using namespace std; const int N=1e4+10; int n,m,s; vector<pair<int,int>> adj[N]; bool v[N],dfs[N]; int d[N]; bool flag; void spfa_dfs(int x) { v[x]=true; for(auto [y,w]:adj[x]) { if(d[y]>d[x]+w) { if(v[y]) { flag=true; return ; } d[y]=d[x]+w; spfa_dfs(y); } } v[x]=false; } int main() { scanf("%d%d%d",&n,&m,&s); while(m--) { int x,y,w; scanf("%d%d%d",&x,&y,&w); adj[x].emplace_back(y,w); } memset(d,0x3f,sizeof d); d[s]=0; spfa_dfs(s); for(int i=1;i<=n;i++) printf("%d ",d[i]==0x3f3f3f3f?INT_MAX:d[i]); return 0; }

__EOF__

本文作者acwing_zyy
本文链接https://www.cnblogs.com/zyyun/p/15319199.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zyy2001  阅读(72)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示