Dijksta DFS求最短路徑問題

2021-10-05 23:12:41 字數 3738 閱讀 1502

對於簡單的求最短路徑的問題,用dijkstra演算法就可以實現。當然,對於加了第二標尺的:比如:如果最短路徑有多條,選擇邊權最小的(花費最小)或者是點權最大的(物質數目多的),也可以用dijkstra演算法,在路徑相等的時候去更新第二標尺。然而,對於一些有多個標尺等更複雜的問題的時候。用dijkstra+dfs演算法。難度會降低許多。

這個演算法的思想是這樣的:首先通過dijkstra演算法計算出最短路徑,並且得到每個結點的前驅結點(也就是通過該前驅結點可以使得該點到起點的距離最小,這樣的結點可能是不唯一的)。這樣就可以得到所有的最短路徑,然後我們只需要在所有的最短路徑中計算出第2,第3等標尺。更新最優路徑即可。

該演算法和之前的類似,只不過之前用的是乙個陣列pre[n]來記錄每個頂點的前驅結點。這裡需要用vectorpre[n]來記錄每乙個頂點的前驅結點(因為結果可能不止乙個)。同時,當存在頂點u,使得u到v的距離可以更優時,需要先清空pre[v]中的結點,然後將u加入。若存在相等的情況,則直接將u加入到v中。

#include

#include

#include

using

namespace std;

const

int inf =

0x3fffffff

;const

int maxn =

520;

int g[maxn]

[maxn]

;//儲存圖

vector<

int>pre[maxn]

;//記錄每個頂點的前驅結點

vector<

int>path,temppath;

//記錄最終路徑和臨時路徑

int optvalue = inf;

//第二標尺

int d[maxn]

;//最短路徑長度

bool vis[maxn]=;

int n,m,st,ed;

//頂點數,邊數,起點,終點

//找最短路徑

void

dijskstra

(int s)}if

(u ==-1

)return

; vis[u]

=true

;for

(int v =

0; v (g[u]

[v]+ d[u]

== d[v])}

}}}

dfs是乙個遞迴函式,考慮遞迴邊界和遞迴式。遞迴邊界就是到達起點。而遞迴式就是在到達起點前每次遞迴的去遍歷pre[v]中的點。這裡要注意最短路徑的求法。用temppath來存放最短的路徑。在訪問v頂點時就可以把該頂點加入到temppath中,然後遞迴遍歷pre[v]。要注意在到達起點的時候需要將起點也加入到temppath中,這時候temppath就存放了起點到終點的逆序。在此基礎上就可以進行其他標尺的計算了。然後需要壓出temppath中最後加入的結點(起點),該層遞迴結束。

//這裡以花費為第二標尺為例

void

dfs(

int v)

if(value < optvalue)

temppath.

pop_back()

;//彈出起點

return;}

temppath.

push_back

(v);

//壓入當前結點

for(

int i=

0; i.size()

; i++

) temppath.

pop_back()

;//for迴圈結束,說明以末尾temppath的結點去更新最短路徑的情況已經列舉完,需要彈出

}

通過上面的計算,最佳路徑被儲存在path中,最小花費(第二標尺)是optvalue中。最短距離在d[n]中。這樣會很容易求出答案。

最後記一到pat a 1087 all roads lead to rome 的題目。

這道題目第一標尺是花費(可以看作是結點之間的距離)。在花費相同的情況下,第二標尺是點權之和。若點權之和還是相同,這一平均點權最大來衡量最優。這道題用dijkstra+dfs就容易做的多。因為在最短路徑找到的情況下,求出最短路徑上的點權之和和平均點權十分容易。**如下:注意這裡需要將城市名和下標對應。自己在解題的時候,在城市名和點權輸入的時候只映**城市名到下標,忘了對映下標到城市名。。。結果不知道為何例子跑得出來就是一直是0分。。。

#include

#include

#include

#include

#include

using

namespace std;

const

int inf =

0x3fffffff

;const

int maxn =

250;

int g[maxn]

[maxn]

;int d[maxn]

,weight[maxn]

;//最短路徑(花費),結點權重

bool vis[maxn]=;

vector<

int>pre[maxn]

;//記錄前驅結點

vector<

int>temppath,path;0;

0;int n,m,st;

//結點數,路徑條數,起點

mapint>citytoindex;

map<

int,string>indextocity;

int nums =0;

//最短路徑的條數

void

dijsktra

(int s)}if

(u ==-1

)return

; vis[u]

=true

;for

(int v=

0; v)else

if(d[u]

+g[u]

[v]==d[v])}

}}}void

dfs(

int v)

1.0(temppath.

size()

-1);

ifelseif}

temppath.

pop_back()

;return;}

temppath.

push_back

(v);

for(

int i=

0; i.size()

;i++

) temppath.

pop_back()

;}intmain()

//初始化為無窮

fill

(g[0

],g[0]

+maxn*maxn,inf)

;for

(int i=

0; i)dijsktra(0

);int rom = citytoindex[

"rom"];

dfs(rom)

;printf

("%d %d %d %d\n"

,nums,d[rom]

(int

;for

(int i = path.

size()

-1; i>=

0; i--

)return0;

}

最短路 求最長最短路,求最短路的路徑

hdu 1595 find the longest of the shortest include include include include include include include include include include include include include defi...

求最短路徑

從源點到終點的路徑可能存在三種情況 1.沒有路徑 2.只有一條路徑 3.有多條路徑 思路 按照路徑長度遞增的次序從源點到終點的路徑。假設gra ph graph graph 為有向網的鄰接矩陣,s ss為已找到最短路徑結點的集合,其初始狀態為只含乙個頂點,即源點。另設乙個一維陣列dis t n di...

求最短路徑(dijkstra)

因為要做一道題牽扯到最小路徑的演算法,所以就看了看締結斯特拉演算法。看了演算法導論上面的介紹不明白,只好下了乙個 自己去看。單源圖最短路徑求法 int dijkstra int from,int to int map n s u 1 for i 0 i 看了之後自己總結的一點點的經驗 締結斯特拉演算...