參考鏈結
spfa**鏈結
解題過程
讀入連線關係,注意這裡有坑,卡10分,具體坑看**中注釋。
預處理小路連線,這裡使用floyd演算法對小路連小路進行合併,主要目的就是在使用spfa演算法求解時不用再考慮小路連小路的情況,因為如果在使用spfa演算法時考慮小路連小路則難以計算疲勞值。
使用spfa求解最小疲勞值,先說一下spfa演算法,它的思路和dijkstra是相似的。dijkstra演算法的思想就是不斷地在距離矩陣中尋找離源節點最近的點作為中間接節點,然後嘗試使用中間節點去更新其他節點到源節點的距離,整個過程用visit陣列做標記,標記該點是否已被訪問,所以每個點只被選擇一次。而spfa演算法的思路略有不同,下面列出**中的演算法描述以及形式演算法描述。
spfa演算法採用圖的儲存結構是鄰接表,方法是動態優化逼近法。演算法中設立了乙個先進先出的佇列queue用來儲存待優化的頂點 ,優化時從此佇列裡順序取出乙個點w,並且用w點的當前路徑d[w]去優化調整其它各點的路徑值d[j],若有調整,即 d[j]的值改小了,就將 j點放入queue佇列以待繼續進一步優化。反覆從queue佇列裡取出點來對當前最短路徑進行優化,直至隊空不需要再優化為止,此時d陣列裡就儲存了從源點到各點的最短路徑值 。spfa演算法中,使用兩個距離矩陣進行計算,dis[wide][i][j]表示最後一條路為大路的i,j間的最小疲勞值,同理dis[narrow][i][j]表示最後一條為小路,分3種情況對dis陣列進行更新,大路連大路,大路連小路,小路連大路,前面已經解釋了為什麼這裡沒有小路連小路的情況。最後更新完畢後,min(dis[wide][1][n],dis[narrow][1][n])就是想要的答案。
#include
#define maxn 505
using
namespace std;
typedef
long
long ll;
int n,m;
ll g[2]
[maxn]
[maxn]
;bool inque[maxn]
;ll dis[2]
[maxn]
;const ll inf =
1e18
;const
int narrow =1;
const
int wide =0;
void
spfa
(int start,
int n)
queue<
int> q;
q.push
(start);
dis[narrow]
[start]=0
; dis[wide]
[start]=0
; inque[start]
=true
;// id為start的點入佇列
while
(!q.
empty()
)}if(dis[wide]
[i]> dis[narrow]
[u]+ v)
//大路後接小路 }if
(g[narrow]
[u][i]
!= inf)
//能通過小路連連線}}
}}}int
main
(int argc,
char
const
*ar**)
//先用floyd演算法計算i,j間小路距離
for(
int i =
1;i <= n; i++)}
}// spfa 求距離
spfa(1
,n);
cout <<
min(dis[narrow]
[n],dis[wide]
[n])
<< endl;
return0;
}
CCF 201712 4 行車路線
思路 用兩個陣列維護到達某個點的最小大路距離和最小小路距離,注意結果中間過程可能爆int,不加long long 只有70分。有一種特殊情況就是通過走兩次大路,消除連續的小路值,這裡就是用兩個陣列維護的原因。include using namespace std const int maxn 100...
CCF201712 4 行車路線
一 題目大意 問題描述 小明和小芳出去鄉村玩,小明負責開車,小芳來導航。小芳將可能的道路分為大道和小道。大道比較好走,每走1公里小明會增加1的疲勞度。小道不好走,如果連續走小道,小明的疲勞值會快速增加,連續走 s公里小明會增加 s2的疲勞度。例如 有5個路口,1號路口到2號路口為小道,2號路口到3號...
ccf 2017 12 4行車路線
dijkstra變形,注意點 1.雖然題目說最終答案不會超過 10 6,但是中間過程可能超int啊 超了以後溢位變小,可能會影響到最後的解 所以還是乖乖用long long 儲存吧 2.圖的話 一定要考慮重邊和反向邊 還是只有70分 看到網上直接用sum i 記錄以當前小路為結尾的前面的連續小路之和...