圖的最短路徑問題(一)--深度優先搜尋演算法解決單源單向圖
阿新 • • 發佈:2022-03-08
本人在部落格園的第一篇題解,日期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權值w10 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錯誤!棧溢位。
解決辦法:換其他演算法,待更新。