7-3 最短路径 (20 分)(分支限界+思路+详解)
一:題目
給定一個有N個頂點和E條邊的無向圖,頂點從0到N?1編號。請判斷給定的兩個頂點之間是否有路徑存在。如果存在,給出最短路徑長度。 這里定義頂點到自身的最短路徑長度為0。 進行搜索時,假設我們總是從編號最小的頂點出發,按編號遞增的順序訪問鄰接點。
輸入格式:
輸入第1行給出2個整數N(0<N≤10)和E,分別是圖的頂點數和邊數。 隨后E行,每行給出一條邊的兩個頂點。每行中的數字之間用1空格分隔。 最后一行給出兩個頂點編號i,j(0≤i,j<N),i和j之間用空格分隔。
輸出格式:
如果i和j之間存在路徑,則輸出"The length of the shortest path between i and j is X.",X為最短路徑長度, 否則輸出"There is no path between i and j."。
輸入樣例1:
7 6 0 1 2 3 1 4 0 2 1 3 5 6 0 3結尾無空行
輸出樣例1:
結尾無空行
輸入樣例2:
結尾無空行
輸出樣例2:
二:思路
分析:1.這個題沒給邊的權值,但我們通過示例可以大概知道默認的為 每條邊的權值為1
思路:1.先判斷輸入的值之間是否有路徑,可以通過DFS來遍歷其中一個頂點的所有鄰接點
如果另一個鄰接點沒有在其中,那么就說明 其是不通的
2.如果兩個點是相連通的,那么我們接下來就是BFS遍歷
3.我們將圖的信息轉換成樹的結構,我們在遍歷樹的時候采用的就是BFS
1>:首先我們將給定的兩個結點的其中一個結點入隊,接下來,將其出隊當作擴展結點
這個新節點(在樹當中的)有自己路徑,還有權值和,以及層數。
2>:然后就判斷這個結點(樹)是否已經到達了目標結點,如果到,那么判斷這個結點
的路徑和跟bestw的值看是否更新,
如果沒到目標結點,判斷其路徑和跟已知bestw 如果比起大就進行剪枝操作
再接下來,就是開始遍歷其鄰接點入隊操作。
4.注意代碼中的 node.x[t] 這其中 t代表的是層數,node.x[t]代表的是圖的一個結點號
三:上碼
/**分析:1.這個題沒給邊的權值,但我們通過示例可以大概知道默認的為 每條邊的權值為1 思路:1.先判斷輸入的值之間是否有路徑,可以通過DFS來遍歷其中一個頂點的所有鄰接點如果另一個鄰接點沒有在其中,那么就說明 其是不通的 2.如果兩個點是相連通的,那么我們接下來就是BFS遍歷 3.我們將圖的信息轉換成樹的結構,我們在遍歷樹的時候采用的就是BFS1>:首先我們將給定的兩個結點的其中一個結點入隊,接下來,將其出隊當作擴展結點 這個新節點(在樹當中的)有自己路徑,還有權值和,以及層數。2>:然后就判斷這個結點(樹)是否已經到達了目標結點,如果到,那么判斷這個結點的路徑和跟bestw的值看是否更新,如果沒到目標結點,判斷其路徑和跟已知bestw 如果比起大就進行剪枝操作再接下來,就是開始遍歷其鄰接點入隊操作。 4.注意代碼中的 node.x[t] 這其中 t代表的是層數,node.x[t]代表的是圖的一個結點號 */#include<bits/stdc++.h> using namespace std;int INF = 999999; int maps[11][11];//存圖用的數組。 int N,M; int bestw = INF; int cnt = 0; int vis2[11] = {0};struct Node{int x[100];//記錄樹的路徑int layer;//記錄層數int cl;//記錄已經走過的路徑長度 }; bool operator<(const Node& a,const Node& b){return a.cl > b.cl;//升序處理 小的數在前面 } //判斷是否可達 void dfs(int a,int b){if(a == b){cnt = 1;return;} vis2[a] = 1;for(int i = 0; i < N; i++){if(vis2[i] != 1 && maps[a][i] == 1){ dfs(i,b); }} // cout << "wyj"; } // //求取最短路徑 void bfs(int a,int b){priority_queue<Node>q; Node node1;node1.cl = 0;node1.layer = 0;//我們是從第0層開始的 for(int i = 0; i < N; i++){//初始化路徑 node1.x[i] = i; } node1.x[0] = a;q.push(node1);while(!q.empty()){ int vis[11] = {0};vis[a] = 1;Node newnode;//擴展結點 newnode = q.top();q.pop();int t1 = newnode.layer;//代表當前的層數 int t2 = newnode.x[t1];//代表當前所到達的結點號 //比較該節點的路徑中,是否到達了目標結點if(t2 == b) {if(newnode.cl < bestw){bestw = newnode.cl;}else{//到達目標結點 如果還未成功的話,那就不用繼續往下遍歷了 continue;} }if(newnode.cl >= bestw)//進行剪枝操作 continue;//將其擴展結點的鄰接點入隊for(int j = 0; j < N; j++){if(vis[j] != 1 && newnode.cl + maps[t2][j] < bestw) {int flag = 1; for(int k = 0; k < t1; k++){if(newnode.x[k] == j){flag = 0; } } if(flag == 0) continue; //這里主要處理的就是 不讓這個路徑往回走 vis[j] = 1; //我們創建一個新的結點(在排列樹當中) Node node2;node2.cl = newnode.cl + maps[t2][j];node2.layer = t1 + 1;for(int i = 0; i < N; i++){node2.x[i] = newnode.x[i];} swap(node2.x[t1+1],j);//t1代表的是層數,node.x[t1]代表該層數所對應圖當中的結點號 q.push(node2); } } } } int main(){ int target1,target2;//兩個目標結點 cin >> N >> M;for(int i = 0; i < N; i++){for(int j = 0; j < N; j++){if(i == j){maps[i][j] = 0;}maps[i][j] = INF;}}for(int i = 0; i < M; i++){int side1,side2;cin >> side1 >> side2;maps[side1][side2] = 1;maps[side2][side1] = 1; }cin >> target1 >> target2; dfs(target1,target2);if(cnt == 0){cout << "There is no path between "<< target1 <<" and " << target2 << ".";} else{bfs(target1,target2);cout << "The length of the shortest path between "<<target1 << " and "<< target2<<" is "<< bestw<<"."; }} //7 6 //0 1 //2 3 //1 4 //0 2 //1 3 //5 6 //0 6//7 7 //0 1 //2 3 //1 4 //0 2 //1 3 //5 6 //4 5 //0 6//7 7 //0 1 //2 3 //1 4 //0 2 //1 3 //5 6 //4 5 //6 2//7 7 //0 1 //2 3 //1 4 //0 2 //1 3 //5 6 //4 5 //4 2四:總結
分支限界如果只是會BFS,是遠遠不夠的,即便我提前已經做過BFS的練習題了,其還是有一定 相當的難度,注意自己一定要畫出相應的圖解,可以幫助理解算法思想和構思代碼
隨手拍照,跟著考研上凌晨自習,感觸頗多,沒有了所謂大家的卷,其實都是在為自己人生路去努力拼搏,太喜歡這種學習的氛圍了,感覺像是回到了高中,那種簡單純碎的學習和快樂 加油 大家
總結
以上是生活随笔為你收集整理的7-3 最短路径 (20 分)(分支限界+思路+详解)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 钉钉怎么退出原来的公司加入新公司
- 下一篇: jdbc的预处理中如何处理模糊查询