搜索与图论复习2最短路

embedded/2025/2/4 9:52:54/

单源最短路---所有边权是正数(Dijkstra算法O(n^2)--稠密图(邻接矩阵)和堆优化的Dijkstra算法O(mlogn)--稀疏图(邻接表)) 或存在负边权(Bellman-ford贝尔曼福特算法O(nm)和SPFA一般O(m) 最坏O(nm)  )

多源最短路---Floyd算法O(n^3)

一、迪杰斯特拉算法(Dijkstra):1dist[1]=0,dist[v]=正无穷。2for(v的0~n),s是当前已经确定最短路径的点,t是不在s中的距离最近的点,t放进s中,用t更新其他点的距离(dist[x]>dist[t]+w)更新。通过邻接矩阵存图。

#include<iostream>
#include<cstring> 
using namespace std;
const int N=510;
int n,m;
int g[N][N];
int dist[N];
bool st[N];//确定最短路 
int dijkstra(){memset(dist,0x3f,sizeof(dist));dist[1]=0;//起点 for(int i=0;i<n;i++){int t=-1;for(int j=1;j<=n;j++){if(!st[j]&&(t==-1||dist[t]>dist[j]))t=j;//找到dist最小的点 }if(t==n)break;//优化 st[t]=true;for(int j=1;j<=n;j++){dist[j]=min(dist[j],dist[t]+g[t][j]);}}if(dist[n]==0x3f3f3f3f)return -1;else return dist[n];
}
int main(){cin>>n>>m;memset(g,0x3f,sizeof(g));while(m--){int a,b,c;cin>>a>>b>>c;g[a][b]=min(g[a][b],c);}int t=dijkstra();cout<<t<<endl;return 0;
}

二、堆优化的迪杰斯特拉算法:优化在n个数中找距离最近的点O(n^2)用堆优化

#include<iostream>
#include<cstring> 
#include<queue> 
using namespace std;
typedef pair<int,int>PII;
const int N=150010;
int n,m;
int h[N],e[N],ne[N],idx,w[N];//权重 
int dist[N];
bool st[N];//是否已经确定最短路 
void add(int a,int b,int c){e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
int dijkstra(){memset(dist,0x3f,sizeof(dist));dist[1]=0;//起点 priority_queue<PII,vector<PII>,greater<PII>>heap;heap.push({0,1});//从1点开始,0为距离 while(heap.size()){auto t=heap.top();heap.pop();int ver=t.second,distance=t.first;if(st[ver])continue;st[ver]=true; for(int i=h[ver];i!=-1;i=ne[i]){int j=e[i];if(dist[j]>distance+w[i]){dist[j]=distance+w[i];heap.push({dist[j],j}); }}}if(dist[n]==0x3f3f3f3f)return -1;else return dist[n];
}
int main(){cin>>n>>m;memset(h,-1,sizeof(h));while(m--){int a,b,c;cin>>a>>b>>c;add(a,b,c);}int t=dijkstra();cout<<t<<endl;return 0;
}

三、Bellman-Ford算法for循环n次,(备份)for所有边a,b,w表示所有a到b的边权值为w,(松弛),处理有福权边,能判断是否有负环(但是一般用SPFA做)

    • 第 k 次松弛:找到经过最多 k 条边的最短路径。

  • 通过多次松弛,算法可以逐步覆盖从起点到所有节点的所有可能路径

#include<iostream>
#include<cstring>
using namespace std;
const int N=510,M=10010;
int n,m,k;
int dist[N],backup[N];
struct Edge{int a,b,w;
}edges[M];
int bellman_ford(){memset(dist,0x3f,sizeof(dist));dist[1]=0;for(int i=0;i<k;i++){memcpy(backup,dist,sizeof(dist));for(int j=0;j<m;j++){int a=edges[j].a,b=edges[j].b,w=edges[j].w;dist[b]=min(dist[b],backup[a]+w);}}if(dist[n]>0x3f3f3f3f/2)return -0x3f3f3f3f;else return dist[n];
}
int main(){cin>>n>>m>>k;for(int i=0;i<m;i++){int a,b,c;cin>>a>>b>>c;edges[i]={a,b,c};}int t=bellman_ford();if(t==-0x3f3f3f3f)cout<<"impossible"<<endl;else cout<<t<<endl;return 0;
}

四、SPFA算法:用队列,只要有变小就取出队头,更新t的所有出边,成功就加入队列(更新过谁就拿谁来操作)通过队列优化 Bellman-Ford 算法,只对距离发生变化的节点进行松弛操作。

#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
int n,m;
const int N=100010;
int dist[N];
bool st[N];
int h[N],e[N],ne[N],idx,w[N];
void add(int a,int b,int c){e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
int spfa(){memset(dist,0x3f,sizeof(dist));dist[1]=0;queue<int>q;q.push(1);st[1]=true;while(q.size()){int t=q.front();q.pop();st[t]=false;for(int i=h[t];i!=-1;i=ne[i]){int j=e[i];if(dist[j]>dist[t]+w[i]){dist[j]=dist[t]+w[i];if(!st[j]){q.push(j);st[j]=true;}}}}if(dist[n]==0x3f3f3f3f)return -0x3f3f3f3f;return dist[n];
}
int main(){cin>>n>>m;memset(h,-1,sizeof(h));while(m--){int a,b,c;cin>>a>>b>>c;add(a,b,c);}int t=spfa();if(t==-0x3f3f3f3f)cout<<"impossible"<<endl;else cout<<t<<endl;return 0;
}

补充负环判断:维护cnt[x]=cnt[t]+1,的数组,如果cnt[x]>=n存在负环。

#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int N=2010,M=10010;
int h[N],e[M],ne[M],idx,w[M];
int dist[N],cnt[N];
bool st[N];
int n,m;
void add(int a,int b,int c){e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
int spfa(){queue<int>q;for(int i=1;i<=n;i++){q.push(i);st[i]=true;}while(q.size()){int t=q.front();q.pop();st[t]=false;for(int i=h[t];i!=-1;i=ne[i]){int j=e[i];if(dist[j]>dist[t]+w[i]){dist[j]=dist[t]+w[i];cnt[j]=cnt[t]+1;if(cnt[j]>=n)return true;if(!st[j]){q.push(j);st[j]=true;}}}}return false;
}
int main(){cin.tie(0),cout.tie(0);ios::sync_with_stdio(false);cin>>n>>m;memset(h,-1,sizeof(h));while(m--){int a,b,c;cin>>a>>b>>c;add(a,b,c);}if(spfa())cout<<"Yes"<<endl;else cout<<"No"<<endl;return 0;
}

五、Floyd算法:基于动态规划三层for枚举d(i,j)=min(d(i,j),d(i,k)+d(k,j))。

#include<iostream>
#include<cstring> 
using namespace std;
const int N=210,INF=1e9;
int n,m,Q;
int d[N][N];
void floyd(){for(int k=1;k<=n;k++){for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){d[i][j]=min(d[i][j],d[i][k]+d[k][j]);}}}
}
int main(){cin>>n>>m>>Q;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){if(i==j)d[i][j]=0;else d[i][j]=INF;}}while(m--){int a,b,w;cin>>a>>b>>w;d[a][b]=min(d[a][b],w);}floyd();while(Q--){int a,b;cin>>a>>b;if(d[a][b]>INF/2)cout<<"impossible"<<endl;else cout<<d[a][b]<<endl;}return 0;
}


http://www.ppmy.cn/embedded/159432.html

相关文章

Dijkstra算法解析

Dijkstra算法&#xff0c;用于求解图中从一个起点到其他所有节点的最短路径。解决单源最短路径问题的有效方法。 条件 有向 带权路径 时间复杂度 O&#xff08;n平方&#xff09; 方法步骤 1 把图上的点分为两个集合 要求的起点 和除了起点之外的点 。能直达的写上权值 不…

登录认证(5):过滤器:Filter

统一拦截 上文我们提到&#xff08;登录认证&#xff08;4&#xff09;&#xff1a;令牌技术&#xff09;&#xff0c;现在大部分项目都使用JWT令牌来进行会话跟踪&#xff0c;来完成登录功能。有了JWT令牌可以标识用户的登录状态&#xff0c;但是完整的登录逻辑如图所示&…

Chromium132 编译指南 - Android 篇(五):获取源码

1. 引言 在前面的章节中&#xff0c;我们详细介绍了编译 Chromium 132 for Android 所需的系统和硬件要求&#xff0c;以及如何配置基础开发环境和 depot_tools。完成这些准备工作后&#xff0c;下一步就是获取 Chromium 的源代码。获取源代码是编译 Chromium 的关键步骤&…

设计模式 - 行为模式_Template Method Pattern模板方法模式在数据处理中的应用

文章目录 概述1. 核心思想2. 结构3. 示例代码4. 优点5. 缺点6. 适用场景7. 案例&#xff1a;模板方法模式在数据处理中的应用案例背景UML搭建抽象基类 - 数据处理的 “总指挥”子类定制 - 适配不同供应商供应商 A 的数据处理器供应商 B 的数据处理器 在业务代码中整合运用 8. 总…

Day 20 卡玛笔记

这是基于代码随想录的每日打卡 235. 二叉搜索树的最近公共祖先 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个结点 p、q&#xff0c;最近公共祖先表示为一个结点 x&#xff0c;满足 x 是 …

使用PaddlePaddle实现逻辑回归:从训练到模型保存与加载

1. 引入必要的库 首先&#xff0c;需要引入必要的库。PaddlePaddle用于构建和训练模型&#xff0c;pandas和numpy用于数据处理&#xff0c;matplotlib用于结果的可视化。 import paddle import pandas as pd import numpy as np import matplotlib.pyplot as plt 2. 加载自定…

61.异步编程1 C#例子 WPF例子

和普通的任务绑定不太相同的部分如下&#xff1a; public MainWindowViewModel(){FetchUserInfoCommand new RelayCommand(async (param) > await FetchUserInfoAsync());}private async Task FetchUserInfoAsync(){// 模拟异步操作&#xff0c;比如网络请求await Task.Del…

【14】WLC3504 HA配置实例

1.概述 本文档使用 Cisco WLC 3504 实现无线控制器的高可用性。这里所指的HA是指WLC设备box-to-box的冗余。换句话说,即1:1的设备冗余,其中一个 WLC 将处于Active活动状态,而第二个 WLC 将处于Standby-hot热待机状态,通过RP冗余端口持续监控活动 WLC 的运行状况。两个 WLC…