SPFA解決帶有負環的單源最短路問題

2021-10-05 03:30:28 字數 2873 閱讀 3306

這一晚,tt 做了個美夢!

在夢中,tt 的願望成真了,他成為了喵星的統領!喵星上有 n 個商業城市,編號 1 ~ n,其中 1 號城市是 tt 所在的城市,即首都。

喵星上共有 m 條有向道路供商業城市相互往來。但是隨著喵星商業的日漸繁榮,有些道路變得非常擁擠。正在 tt 為之苦惱之時,他的魔法小貓咪提出了乙個解決方案!tt 欣然接受並針對該方案頒布了一項新的政策。

具體政策如下:對每乙個商業城市標記乙個正整數,表示其繁榮程度,當每乙隻喵沿道路從乙個商業城市走到另乙個商業城市時,tt 都會收取它們(目的地繁榮程度 - 出發地繁榮程度)^ 3 的稅。

tt 打算測試一下這項政策是否合理,因此他想知道從首都出發,走到其他城市至少要交多少的稅,如果總金額小於 3 或者無法到達請悄咪咪地打出 『?』。

第一行輸入 t,表明共有 t 組資料。(1 <= t <= 50)

對於每一組資料,第一行輸入 n,表示點的個數。(1 <= n <= 200)

第二行輸入 n 個整數,表示 1 ~ n 點的權值 a[i]。(0 <= a[i] <= 20)

第三行輸入 m,表示有向道路的條數。(0 <= m <= 100000)

接下來 m 行,每行有兩個整數 a b,表示存在一條 a 到 b 的有向道路。

接下來給出乙個整數 q,表示詢問個數。(0 <= q <= 100000)

每一次詢問給出乙個 p,表示求 1 號點到 p 號點的最少稅費。

每個詢問輸出一行,如果不可達或稅費小於 3 則輸出 『?』

256

78910

6122

3341

5544

5245

10124

4567

89101012

2331

1445

5667

7889

91023

10

case 1:3

4case 2:?

?

• 題目要求從 1 出發到其他點花費最少的錢,相當於求 1 到其他點的最短路。

• 值得注意的一點是,經過一條道路,tt 收的稅可能是負數。

• 圖中存在負權邊,這是乙個含負權邊的單源最短路徑問題

• 當什麼情況下會輸出 『?』

①不可達

②最短路存在且小於 3

③最短路不存在

• 因此需要我們用spfa演算法判斷負環,那些通過負環可以到達的點的最短路均不存在

• 找到負環後,將負環所在連通塊裡的點打上標記即可(bfs跑一遍即可)

//spfa

int vis[maxn]

,cn[maxn]

,dis[maxn]

;//vis - 點在不在佇列中 cn【x】 - 點x最短路徑上經過的點數 dis - 距離

queue<

int> q;

void

spfa

(int s)

//佇列中加入初始點

dis[s]=0

; vis[s]=1

; q.

push

(s);

while

(q.size()

)if(!vis[v]

&&!flag[v]

)//當前點v沒有在佇列中,並且不是負環的一部分}}

}}

#include

#include

#include

#include

#include

#include

#include

using

namespace std;

const

int maxn =

205;

const

int maxm =

1e5+5;

const

int inf =

1e5;

int n,m,a[maxn]

;//鏈式前向星

struct edge

edge[maxm]

;int head[maxn]

,cnt;

void

init()

void

add(

int u,

int v,

int w)

//bfs

bool flag[maxn]

;void

bfs(

int s)}}

}//spfa

int vis[maxn]

,cn[maxn]

,dis[maxn]

;//vis - 點在不在佇列中 cn【x】 - 點x最短路徑上經過的點數 dis - 距離

queue<

int> q;

void

spfa

(int s)

//佇列中加入初始點

dis[s]=0

; vis[s]=1

; q.

push

(s);

while

(q.size()

)if(!vis[v]

&&!flag[v]

)//當前點v沒有在佇列中,並且不是負環的一部分}}

}}intmain()

spfa(1

);printf

("case %d:\n"

,count)

;int num,p;

scanf

("%d"

,&num)

;while

(num--)}

return0;

}

單源負邊最短路演算法 Spfa

求單源最短路的spfa演算法的全稱是 shortest path faster algorithm。很多時候,給定的圖存在負權邊,這時類似dijkstra等演算法便沒有了用武之地,而bellman ford演算法的複雜度又過高,spfa演算法便派上用場了。有人稱spfa演算法是最短路的萬能演算法。簡...

最短路專題 spfa判斷負環

題目大意 有多種匯幣,匯幣之間可以交換,這需要手續費,當你用100a幣交換b幣時,a到b的匯率是29.75,手續費是0.39,那麼你可以得到 100 0.39 29.75 2963.3975 b幣。問s幣的金額經過交換最終得到的s幣金額數能否增加 貨幣的交換是可以重複多次的,如果有乙個環使得某種貨幣...

SPFA單源最短路詳解

適用範圍 給定的圖存在負權邊,這時類似dijkstra等演算法便沒有了用武之地,而bellman ford演算法的複雜度又過高,spfa演算法便派上用場了。我們約定有向加權圖g不存在負權迴路,即最短路徑一定存在。當然,我們可以在執行該演算法前做一次拓撲排序,以判斷是否存在負權迴路,但這不是我們討論的...