图论——Bellman-Ford算法
在这篇里,我们讲到,对于有负权值的情况下,一般用Bellman_Ford。
今天就来详述一下Bellman_Ford与其例题。
Bellman_Ford的思想非常简单,首先第一层枚举点,第二层枚举每一条边。
与其说第一层是枚举,其实不如说它是单纯循环,因为,有些题目中,第一层就是单纯循环,对于需要枚举节点的题目来说,它还是一样的写法。
第二层循环有3个变量:a,b,w,a表示边的起点,b表示边的终点,w表示边的权值,Bellman_Ford的存边方式很灵活,只要保证能遍历到每条边的起点、终点、权值就可以了,不一定非得用邻接表或邻接矩阵。我们可以开一个结构体,里面放3个变量:a,b,w;一个结构体数组edge[]既然都用了edge,所以这就是存边用的。
而它循环内执行的操作和Dijkstra十分相像。dis[edge[j].b]=min(dis[edge[j].b],bc[edge[j].a]+edge[j].w);就可以。再看一个例题:
求出从1号点到n号点的最多经过k条边的最短距离,如果无法从1号点走到n号点,输出impossible
这道题只能用Bellman_Ford做,其他均不可以(包括SPFA),在这一题中,第一层循环中,我们枚举的就是k因为只要枚举次数小于k次,就1一定能保证经过的边数小于k。
最后再判断,如果求出的答案是初始值,那么输出不可能就行。
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #include<bits/stdc++.h> using namespace std; int n,m,dis[505],bc[505],aa,bb,ww,k; struct aaa{ int a,b,w; }edge[10005]; int main(){ memset (dis,0x3f, sizeof dis); dis[1]=0; cin>>n>>m>>k; for ( int i=1;i<=m;i++){ cin>>aa>>bb>>ww; edge[i]={aa,bb,ww}; } for ( int i=1;i<=k;i++){ memcpy (bc,dis, sizeof dis); for ( int j=1;j<=m;j++) dis[edge[j].b]=min(dis[edge[j].b],bc[edge[j].a]+edge[j].w); } if (dis[n]>0x3f3f3f3f/2) cout<< "impossible" ; else cout<<dis[n]; return 0; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话