7-2 单源最短路径 (10 分)(思路+详解+邻接表做法)Come Brather!!!!!!!!!!
一:前言
本次題解先展示用鄰接矩陣做的,但其會(huì)出現(xiàn)內(nèi)存超限,因?yàn)榇_實(shí)是臨界矩陣在數(shù)據(jù)很大的時(shí)候相比臨界表是耗內(nèi)存的,但是以前習(xí)慣用臨界矩陣了,所以一上來就用臨界矩陣做了,后來上網(wǎng)查了后知道鄰接矩陣會(huì)內(nèi)存超限,所以后來又用鄰接表寫了一遍。
二:題目
請(qǐng)編寫程序求給定正權(quán)有向圖的單源最短路徑長度。圖中包含n個(gè)頂點(diǎn),編號(hào)為0至n-1,以頂點(diǎn)0作為源點(diǎn)。
輸入格式:
輸入第一行為兩個(gè)正整數(shù)n和e,分別表示圖的頂點(diǎn)數(shù)和邊數(shù),其中n不超過20000,e不超過1000。接下來e行表示每條邊的信息,每行為3個(gè)非負(fù)整數(shù)a、b、c,其中a和b表示該邊的端點(diǎn)編號(hào),c表示權(quán)值。各邊并非按端點(diǎn)編號(hào)順序排列。
輸出格式:
輸出為一行整數(shù),為按頂點(diǎn)編號(hào)順序排列的源點(diǎn)0到各頂點(diǎn)的最短路徑長度(不含源點(diǎn)到源點(diǎn)),每個(gè)整數(shù)后一個(gè)空格。如源點(diǎn)到某頂點(diǎn)無最短路徑,則不輸出該條路徑長度。
輸入樣例:
4 4 0 1 1 0 3 1 1 3 1 2 0 1輸出樣例:
1 1三:介紹dijkstra算法
1.dijkstra
無論你用哪種數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)數(shù)據(jù),其算法思想是一樣的,dijkstra算法,單源點(diǎn)最短路徑,其在更新的階段體現(xiàn)了貪心,每次都找最優(yōu)的結(jié),即最小的路徑
2:做題思路
思路:1.首先讀題分析到 這是一個(gè)有向圖
2.單源點(diǎn)最短路徑:確定一個(gè)點(diǎn)為源點(diǎn),其到其他點(diǎn)的最短路徑;本題當(dāng)中
因?yàn)槭怯邢驁D,當(dāng)沒有最短路徑就不輸出了
分析:示例: 4 4
0 1 1
0 3 1
1 3 1
2 0 1
輸出為: 1 1
這是0 到 1 的最短路徑和0到3的最短路徑 而 0到 2無路徑 (2到0有路徑)
3.本題我先用的是臨界矩陣儲(chǔ)存數(shù)據(jù)的會(huì)出現(xiàn)內(nèi)存超限后來改為鄰接表,而體現(xiàn)貪心的部分是代碼中的更新的部分,每次都找最優(yōu)解
4.具體代碼流程需要自己分析示例圖解:這里有我分析的無向圖的圖解,思路和有向圖類似
懂了這個(gè)就懂了本題的寫碼思路了
3.圖示(以無向圖為例,和有向圖思路是一致的)
四:上碼
1.用鄰接矩陣存儲(chǔ)的數(shù)據(jù)(會(huì)出現(xiàn)內(nèi)存超限)
/**思路:1.首先讀題分析到 這是一個(gè)有向圖2.單源點(diǎn)最短路徑:確定一個(gè)點(diǎn)為源點(diǎn),其到其他點(diǎn)的最短路徑;本題當(dāng)中因?yàn)槭怯邢驁D,當(dāng)沒有最短路徑就不輸出了分析:示例: 4 40 1 10 3 11 3 12 0 1 輸出為: 1 1 這是0 到 1 的最短路徑和0到3的最短路徑 而 0到 2無路徑 (2到0有路徑) 3.本題我用的是臨界矩陣儲(chǔ)存數(shù)據(jù)的,而體現(xiàn)貪心的部分是代碼中的更新的部分,每次都找最優(yōu)解 4.具體代碼流程需要自己分析示例圖解:這里有我分析的無向圖的圖解,思路和有向圖類似懂了這個(gè)就懂了本題的寫碼思路了 */ #include<bits/stdc++.h>using namespace std;typedef struct Graph * PtrGraph; typedef struct Graph{int Nv;int Ne;int Date[2276][2274];} graph;int infinite = 99999;//初始化臨界矩陣void CreateGraph(PtrGraph G){cin >> G->Nv >> G->Ne;//初始化臨界矩陣 for(int i = 0; i < G->Nv; i++){for(int j = 0; j < G->Nv; j++){if(i == j){G->Date[i][j] = 0;} else{G->Date[i][j] = infinite;//當(dāng)兩個(gè)點(diǎn)不相連的時(shí)候?yàn)闊o窮大 }} }//向臨界矩陣中賦值for(int k = 0; k < G->Ne; k++){int i,j,w;cin >> i >> j >> w;G->Date[i][j] = w;//這里體現(xiàn)有向圖,即從 i 到 j 在臨界矩陣中有值,而從j到i無值 } } //驗(yàn)證輸出臨界矩陣 // void print_Graph(PtrGraph G) {// for(int i = 0; i < G->Nv; i++){// for(int j = 0; j < G->Nv; j++){// cout << G->Date[i][j] << ' ';// } // cout << endl;// }// }//核心代碼 體現(xiàn)貪心的代碼 每次更新均找距離最短的點(diǎn) void dijkstra(PtrGraph G){int dist[2001];//用于存儲(chǔ)源點(diǎn)到各個(gè)點(diǎn)的最短距離int visited[2001];//用于記錄已經(jīng)訪問了哪個(gè)點(diǎn)的 for(int i = 0; i < G->Nv; i++){dist[i] = G->Date[0][i];//題目給出了源點(diǎn)是 0 } visited[0] = 1;//表示1已經(jīng)訪問過了//更新 while(1){int m = -1;int min = infinite;for(int i = 0; i < G->Nv; i++){if(visited[i] != 1 && dist[i] < min){min = dist[i];m = i; } } if(m == -1){//如果m無變化,說明圖中的各點(diǎn)已經(jīng)更新完了 break;}visited[m] = 1;for(int i = 0; i < G->Nv; i++){if(visited[i] != 1 && min + G->Date[m][i] < dist[i]){//這里注意 min + G->Date[m][i]://表示了一個(gè)源點(diǎn)到其最短的距離(min)的點(diǎn),//然后需要判斷這個(gè)點(diǎn)到其他點(diǎn)的距離加上min和源點(diǎn)到其他點(diǎn)的距離進(jìn)行比較更新dist[i] = min + G->Date[m][i];}} } for(int i = 1; i < G->Nv; i++){if(dist[i] == infinite)continue;else{cout << dist[i] << ' '; } } } int main(){PtrGraph G = (PtrGraph)malloc(sizeof(struct Graph));CreateGraph(G);// print_Graph(G);dijkstra(G);}2:用鄰接表存的正確結(jié)果
#include<bits/stdc++.h> using namespace std; #define max 20001struct Node{int to;//指向邊的結(jié)點(diǎn) int val;//邊的權(quán)值 int next;//指向下一個(gè)結(jié)點(diǎn)的下標(biāo) } node[max];int head[max],n,m,num = 0; int infinite = 99999;//建立鄰接表 void add(int from,int to,int val){num++;node[num].to = to;node[num].val = val;node[num].next = head[from];head[from] = num;//更新head的值,當(dāng)再有從from連接的點(diǎn) 它的下一個(gè)為 num 坐標(biāo) } //dij算法 void dijkstra(){int dist[max];fill(dist, dist + 20001, infinite);int vis[max] = {0};for(int i = head[0]; i != 0; i = node[i].next){//這里是選取源點(diǎn)為0的頂點(diǎn),將和其相連邊的權(quán)值存進(jìn)去了 dist[node[i].to] = node[i].val; //比如:0到1:即 node[i].to = 1表示的是頂點(diǎn), node[i].val = 1 表示0到1這條邊的權(quán)值為1;dist[1] = 1}vis[0] = 1;while(1){int m = -1;int min = infinite;for(int i = 0; i < n; i++){if(vis[i] != 1 && dist[i] < min){min = dist[i];m = i;}}if(m == -1){//已經(jīng)遍歷完了所有結(jié)點(diǎn) break;}vis[m] = 1;//確定m這個(gè)頂點(diǎn) 接下來遍歷 m這個(gè)結(jié)點(diǎn)的鏈表 for(int i = head[m]; i != 0; i = node[i].next){if(vis[node[i].to] != 1 && min + node[i].val < dist[node[i].to]){//vis[node[i].to] != 1如果出現(xiàn) 1到2 和2到1這種情況,那么當(dāng)1已經(jīng)遍歷過,在頂點(diǎn)為2的這個(gè)鏈表中就不用再遍歷了dist[node[i].to] = min + node[i].val;} } } for(int i = 0; i < n; i++){if(dist[i] != infinite){cout << dist[i] << ' ';}} } int main(){memset(head,0,sizeof(head));cin >> n >> m;for(int i = 0; i < m; i++){int from,to,val;cin >> from >> to >> val;add(from,to,val);} //測(cè)試鄰接表的數(shù)據(jù)是否正確 // for(int i = 0; i < n; i++){ // cout << i << ' '; // for(int j = head[i]; j != 0; j = node[j].next){ // cout << node[j].to << ' ' << node[j].val << ' '; // } // cout << endl; // }dijkstra();}//4 4 //0 1 1 //0 3 1 //1 3 1 //2 0 1//鄰接表輸出的數(shù)據(jù) //0 3 1 1 1 //1 3 1 //2 0 1 //3//4 5 //0 1 1 //1 3 2 //0 3 4 //0 2 2 //2 3 3五:知識(shí)速遞(如果兄弟們對(duì)鄰接表不熟悉,可以學(xué)習(xí)下哈)
鄰接表的用法
加油 兄弟們!!!
總結(jié)
以上是生活随笔為你收集整理的7-2 单源最短路径 (10 分)(思路+详解+邻接表做法)Come Brather!!!!!!!!!!的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 神仙菜的功效与作用、禁忌和食用方法
- 下一篇: map容器的使用 逆序遍历map容器当中