網(wǎng)站首頁 編程語言 正文
給定一張有向圖,若對(duì)于圖中的某一條邊(x,y,z),有dist[y]≤dist[x]+z成立,則稱該邊滿足三角形不等式。如果所有邊都滿足三角形不等式,則dist數(shù)組就是所求的最短路。
Bellman-Ford算法
(x,y,z)表示的是一條從 x 出發(fā), 到達(dá) y ,長度為 z 的有向邊。
首先介紹基于迭代的Bellman-Ford算法,它的流程如下:
1.掃描所有邊(x,y,z),若dist[y]>dist[x]+z, 則用dist[x]+z更新dist[y]
2.重復(fù)上述操作,直到?jīng)]有更新操作發(fā)生。
Bellman-Ford算法的時(shí)間復(fù)雜度是O(nm)
通過Bellman-Ford算法我們可以求解有邊數(shù)限制的最短路問題。
例題:AcWing 853. 有邊數(shù)限制的最短路
算法步驟
初始化 dist 數(shù)組為正無窮, dist[1] = 0
(外重循環(huán))循環(huán) i 從 1 到 n ,遍歷 n 次表示:是不經(jīng)過超過 i 條邊到達(dá)終點(diǎn)的最短距離
(內(nèi)重循環(huán))循環(huán) i 從 1 到 m, 遍歷 m 條邊,把所有的邊都進(jìn)行松弛操作:
每次取出兩點(diǎn)以及以及連接他們的權(quán)重 (a,b,w)
用以下公式更新最短距離: dist[b]=min(dist[b],dist[a]+w)
注意點(diǎn):
需要把dist數(shù)組進(jìn)行一個(gè)備份,這樣防止每次更新的時(shí)候出現(xiàn)串聯(lián)
由于存在負(fù)權(quán)邊,所以 return -1 的條件是dist[n]>0x3f3f3f/2
代碼實(shí)現(xiàn)
#include <iostream>
#include <cstring>
using namespace std;
const int N = 510, M = 10010;
struct Edge
{
int a, b, w;
}e[M]; // 存下每一條即可
int dist[N];
int back[N]; // 備份數(shù)組放置串聯(lián)
int n, m, k;
void bellman_ford()
{
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
for(int i = 0; i < k; i ++ ) // 不超過k條邊
{
memcpy(back, dist, sizeof back);
for(int j = 0; j < m; j ++ ) // 遍歷所有邊
{
int a = e[j].a, b = e[j].b, w = e[j].w;
dist[b] = min(dist[b], back[a] + w);
}
}
}
int main()
{
cin >> n >> m >> k;
for(int i = 0; i < m; i ++ )
{
int a, b, w;
scanf("%d%d%d", &a, &b, &w);
e[i] = {a, b, w};
}
bellman_ford();
if(dist[n] > 0x3f3f3f3f / 2) puts("impossible");
else cout << dist[n] << endl;
return 0;
}
SPFA算法
SPFA算法在國際上通稱為“隊(duì)列優(yōu)化的“Bellman-Ford算法”。
SPFA算法的流程如下:
1.建立一個(gè)隊(duì)列,起初隊(duì)列中只含有起點(diǎn)1
2.取出頭結(jié)點(diǎn) x ,掃描它的所有出邊(x,y,z),若dist[y]>dist[x]+z,則使dist[y]用dist[x]+z來更新。同時(shí)若y不再隊(duì)列中,則將y入隊(duì)
在任意時(shí)刻,該算法的隊(duì)列都保持了該拓展的節(jié)點(diǎn)。每次入隊(duì)都相當(dāng)于完成了一次 dist 數(shù)組的更新操作,使其滿足三角不等式。一個(gè)節(jié)點(diǎn)可能會(huì)入隊(duì)、出隊(duì)多次。最終,圖中所有的結(jié)點(diǎn)全部收斂到全部滿足三角不等式的狀態(tài)。
這個(gè)隊(duì)列避免了對(duì)Bellman-Ford算法中不需要拓展的多余結(jié)點(diǎn)的冗余掃描,在隨機(jī)圖上的運(yùn)行效率O(km)級(jí)別,其中 k 是一個(gè)很小的常數(shù)。
代碼實(shí)現(xiàn)
SPFA求最短路
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 1e6 + 10;
int n, m;
int h[N], e[N], w[N], ne[N], idx;
int dist[N];
bool st[N];
void add(int a, int b, int c)
{
e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx ++ ;
}
void spfa()
{
memset(dist, 0x3f, sizeof dist);
queue<int> q;
dist[1] = 0;
st[1] = true;
q.push(1);
while(q.size())
{
int t = q.front();
q.pop();
st[t] = false;
for(int i = h[t]; ~i; 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;
}
}
}
}
}
int main()
{
scanf("%d%d", &n, &m);
memset(h, -1, sizeof h);
while (m -- )
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
add(a, b, c);
}
spfa();
if(dist[n] == 0x3f3f3f3f) puts("impossible");
else printf("%d",dist[n]);
return 0;
}
原文鏈接:https://blog.csdn.net/forever_bryant/article/details/125274273
相關(guān)推薦
- 2022-03-10 你知道如何自定義sort函數(shù)中的比較函數(shù)_C 語言
- 2022-04-23 Linux基于客戶端用戶密鑰登錄服務(wù)端用戶
- 2022-11-27 Oracle?中檢查臨時(shí)表空間的方法_oracle
- 2022-07-31 Python?reflect單例模式反射各個(gè)函數(shù)_python
- 2022-02-19 數(shù)據(jù)結(jié)構(gòu)C語言鏈表的實(shí)現(xiàn)介紹_C 語言
- 2022-08-14 Android?MonoRepo多倉和單倉的差別理論_Android
- 2023-04-07 React替換傳統(tǒng)拷貝方法的Immutable使用_React
- 2022-12-25 Python中你所不知道的星號(hào)?*?用法_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支