題意不說(shuō)了,有特殊要求的最短路。對(duì)于單源最短路,我是無(wú)腦上SPFA,SPFA也寫(xiě)了不下十遍,然而這次沒(méi)有處理好。關(guān)于SPFA,多說(shuō)幾句,個(gè)人感覺(jué)就是優(yōu)化的BFS,優(yōu)化在哪了呢?就是對(duì)入隊(duì)的節(jié)點(diǎn)有標(biāo)準(zhǔn),只有對(duì)當(dāng)前狀態(tài)可能有幫助的節(jié)點(diǎn)才會(huì)入隊(duì),有一種“松弛”的感覺(jué),而且個(gè)人感覺(jué)這其實(shí)是建一棵樹(shù)的過(guò)程。
然而這次在25分卡了好久,最后總算想到了自己哪里沒(méi)考慮周全,這里是AC代碼。題中說(shuō)如果最短路不止一條,取換乘最少的,此結(jié)果唯一。我的做法是dis數(shù)組保存距離,cnt數(shù)組保存換乘次數(shù),preS保存前驅(qū)車(chē)站,preL保存前驅(qū)線路id。對(duì)于隊(duì)首的節(jié)點(diǎn),對(duì)其相連的點(diǎn)做松弛操作,而這里就是關(guān)鍵。距離變短了,肯定要松弛(修改前驅(qū))并入隊(duì);距離不變,但換乘變少,肯定也要修改。那距離和換乘都不變的話,要不要入隊(duì)呢?
答案是肯定的。又回到了本題給出的前提,所謂的結(jié)果唯一,但是中間結(jié)果不一定唯一(聯(lián)想到最優(yōu)子結(jié)構(gòu))。而我最開(kāi)始卻沒(méi)有入隊(duì),也就是代碼第54行,最初寫(xiě)的是“<”號(hào)而不是“<=”,如下,具體的反例注釋在了代碼最后。其實(shí)還有個(gè)問(wèn)題,這樣會(huì)不會(huì)無(wú)限循環(huán)(不停入隊(duì)出隊(duì))?其實(shí)是不會(huì)的,這個(gè)問(wèn)題留給讀者思考。
if (tmp <=cnt[v])
{
……
}
網(wǎng)上大佬們貌似都是清一色的dfs,把整個(gè)路徑都存下來(lái),然后判斷、取舍、輸出,所有的路徑都會(huì)走到,因而不會(huì)出現(xiàn)我這樣的問(wèn)題。其實(shí)只有這類(lèi)“答案不唯一,但是XXX這樣的答案保證唯一”這種情況下才容易發(fā)生我這樣的錯(cuò)誤。所以教訓(xùn)就是:要么考慮周全,想清楚最優(yōu)子結(jié)構(gòu)是否唯一,不唯一怎么辦;要么就采用穩(wěn)妥的方法,多寫(xiě)幾行代碼,比如記錄下所有的路徑,之后再作判斷。