1. 程式人生 > 其它 >圖的最短路徑問題(一)--深度優先搜尋演算法解決單源單向圖

圖的最短路徑問題(一)--深度優先搜尋演算法解決單源單向圖

本人在部落格園的第一篇題解,日期2022年3月8日晚上7點。

前言:本文適合有一定dfs基礎和圖論基礎的人借鑑。

1.深度優先搜尋演算法(Deep First Search):

  不過度贅述,利用遞迴呼叫。下面給出模板。

1 void dfs(引數列表){
2     //剪枝
3 
4     //遞迴結束
5 
6     //遞迴
7     
8 }   

2.題目:(P3371 【模板】單源最短路徑(弱化版) - 洛谷 | 電腦科學教育新生態 (luogu.com.cn))

 

 

 

 

本題中,dfs核心程式碼如下:

 1 void dfs(int cur,int des,int sum){    
2 //剪枝 3 if(sum>=minSum[des])return; 4 //找到目標點,結束遞迴 5 if(cur==des){ 6 minSum[des]=sum;//更新新小值 7 return; 8 } 9 //遞迴 10 for(int i=1;i<=n;i++){ 11 if( edge[cur][i]==-1)continue; 12 dfs(i,des,sum+edge[cur][i]); 13 } 14 }

 

其中,cur表示當前到達的元素,des表示終點元素,sum表示當前已經累計的合。

minSum[des]表示從s到當前終點的最短路徑權值合。

剪枝部分:已經累積的合已然超過了之前搜尋到的最小值,直接結束遞迴。

當cur==des,也就是找到終點元素,當前路徑打通,結束遞迴,並且一定此時有sum<minSum[des]。

這裡的edge[A][B]的值,表示從A->B路徑的權值。

3.下面給出完整程式碼:

 1 /***
 2 
 3 ***/
 4 #include<iostream>
 5 #include<algorithm>
 6 using namespace std;
 7 //點,邊,出發點
 8 // m 行 u v w
 9 // u->v權值w
10 const int Max=20; 11 const int Inf=2147483647; 12 int n,m,s; 13 int edge[Max][Max]; 14 int minSum[Max]; 15 void dfs(int cur,int des,int sum){ 16 //剪枝 17 if(sum>=minSum[des])return; 18 //找到目標點,結束遞迴 19 if(cur==des){ 20 minSum[des]=sum;//更新新小值 21 return; 22 } 23 //遞迴 24 for(int i=1;i<=n;i++){ 25 if( edge[cur][i]==-1)continue; 26 dfs(i,des,sum+edge[cur][i]); 27 } 28 } 29 int main() { 30 cin>>n>>m>>s; 31 for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)edge[i][j]=-1; //初始化鄰接矩陣 32 while(m--){ 33 int u,v,w; 34 cin>>u>>v>>w; 35 edge[u][v]=w; 36 } 37 fill(minSum+1,minSum+n+1,Inf); 38 for(int i=1;i<=n;i++){ 39 dfs(s,i,0); 40 cout<<minSum[i]<<" "; 41 } 42 return 0; 43 } 44 45 46

 

 

其中,edge鄰接矩陣需要初始化,-1表示不連通。

fill()語句語法:fill(填充起始地址,結束地址,填充值); 

用來把陣列整體賦值為一個非0值。

值得注意的是,當資料過大時,會出現stack overflow錯誤!棧溢位。

解決辦法:換其他演算法,待更新。