最短路(floyd,dijkstra,spfa)
最短路
[
思考枚举
原转移为
经空间压缩后为
注:为多源最短路
核心代码:
void floyd(){ for(int k=1;k<=n;k++){ for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ a[i][j]=min(a[i][j],a[i][k]+a[k][j]); } } } }
[
一种基于贪心的算法,每次弹出堆中的点,
对所有与其相连的点进行松弛操作,
然后将松弛成功且还未以其作为松弛起点的点加入堆,
准备下一次松弛。
(松弛,即查看以当前节点为中转点的最短路是否比目标节点的最短路小,小即更新)
注:无法处理负权
核心代码:
typedef pair<int,int> P; struct node{ int to,len; }; //dis为最短路径,mp为临接表,vis为标记数组 void dijkstra(int s){ priority_queue<P,vector<P>,greater<P> >q; dis[s]=0; q.push(P{dis[s],s}); while(!q.empty()){ int l=q.top().second; q.pop(); if(vis[l]){ continue; } vis[l]=1; for(auto v:mp[l]) { if(dis[v.to]>dis[l]+v.len){ dis[v.to]=dis[l]+v.len; q.push(P{dis[v.to],v.to}); } } } }
[
每次弹出队列中的点对周围进行松弛操作,
将松弛成功的点加入队列(不论是否其已经为松弛起点过),
一直执行到没有点可以松弛。
所以spfa可以处理负权环,当一个点被松弛了n次及以上说明该处有负权环。
但是你要是被卡了和floyd坐一桌
核心代码:
struct node{ int to,len; }; //数组意思同上 void spfa(int s){ queue<int>q; dis[s]=0; vis[s]=1; q.push(s); while(!q.empty()){ int l=q.top(); q.pop(); vis[l]=0; for(auto v:mp[l]){ if(dis[v.to]>dis[l]+v.len){ dis[v.to]=dis[l]+v.len; if(!vis[l]){ q.push(v.to); vis[l]=1; } } } } }
1.accoders【一本通图 最短路径算法】 信使 2004
思路:
打一个dijkstra的板子,注意是无向图。
code:
#include<bits/stdc++.h> using namespace std; typedef pair<int,int> P; struct node{ int to,len; }; vector<node>mp[10010]; int dis[10010],vis[10010]; void dij(int s){ priority_queue<P,vector<P>,greater<P> >q; dis[s]=0; q.push(P{dis[s],s}); while(!q.empty()){ int l=q.top().second; q.pop(); if(vis[l]){ continue; } vis[l]=1; for(auto v:mp[l]){ if(dis[v.to]>dis[l]+v.len){ dis[v.to]=dis[l]+v.len; q.push({dis[v.to],v.to}); } } } } int main(){ memset(dis,0x3f3f3f,sizeof dis); int n,m; cin>>n>>m; for(int i=1;i<=m;i++){ int l,r,w; cin>>l>>r>>w; mp[l].push_back({r,w}); mp[r].push_back({l,w}); } dij(1); int ans=-1; for(int i=1;i<=n;i++){ ans=max(ans,dis[i]); } if(ans>=0x3f3f00){ cout<<-1; }else{ cout<<ans; } int _=0; return (_^_^_); }
2.accoders 【一本通提高篇SPFA算法的优化】Wormholes 虫洞2117
思路:
用spfa判断负环。
code:
#include<bits/stdc++.h> using namespace std; const int N=1000010,inf=0x3f3f3f3f; int T; int n,m,k; int num[N],dis[N],vis[N]; struct node{ int to,len; }; vector<node>e[N]; void init(){ memset(dis,inf,sizeof dis); memset(num,0,sizeof num); memset(vis,0,sizeof vis); for(int i=1;i<=n;i++){ e[i].clear(); } } int spfa(int s){ queue<int>q; dis[s]=0; q.push(s); vis[s]=1; num[s]=1; while(!q.empty()){ int u=q.front(); q.pop(); vis[u]=0; for(auto v:e[u]){ if(dis[v.to]>dis[u]+v.len){ dis[v.to]=dis[u]+v.len; if(!vis[v.to]){ num[v.to]++; if(num[v.to]>n-1){ return 0; } q.push(v.to); vis[v.to]=1; } } } } return 1; } int main(){ cin>>T; while(T--){ cin>>n>>m>>k; init(); for(int i=1;i<=m;i++){ int u,v,w; cin>>u>>v>>w; e[u].push_back({v,w}); e[v].push_back({u,w}); } for(int i=1;i<=k;i++){ int u,v,w; cin>>u>>v>>w; e[u].push_back({v,-w}); } if(spfa(1)){ cout<<"NO\n"; }else{ cout<<"YES\n"; } } return 0; }
3.accoders【一本通图 最短路径算法】香甜的黄油2003
思路:
在每一个点跑一遍
注:一个点可能有多个奶牛。
#include<bits/stdc++.h> using namespace std; typedef pair<int,int> P; int dis[1010],sum[1010],vis[1010],fl[1010]; struct node{ int to,len; }; vector<node> mp[1010]; void dijkstra(int s){ priority_queue<P,vector<P>,greater<P> >q; dis[s]=0; q.push(P{dis[s],s}); while(!q.empty()){ int l=q.top().second; q.pop(); if(vis[l]){ continue; } vis[l]=1; for(auto v:mp[l]){ if(dis[v.to]>dis[l]+v.len){ dis[v.to]=dis[l]+v.len; q.push(P{dis[v.to],v.to}); } } } } int main(){ int n,p,c; cin>>n>>p>>c; for(int i=1;i<=n;i++){ int s; cin>>s; fl[s]++; } for(int i=1;i<=c;i++){ int l,r,w; cin>>l>>r>>w; mp[l].push_back({r,w}); mp[r].push_back({l,w}); } for(int i=1;i<=p;i++){ memset(dis,0x3f3f3f3f,sizeof(dis)); memset(vis,0,sizeof(vis)); dijkstra(i); for(int j=1;j<=p;j++){ sum[i]+=dis[j]*fl[j]; } } int mi=2e9; for(int i=1;i<=p;i++){ mi=min(mi,sum[i]); } cout<<mi; return 0; }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!