資料結構實驗之圖論七:驢友計劃 (Dijkstra演算法詳解)
阿新 • • 發佈:2019-01-06
#include<bits/stdc++.h> #define MAX INT_MAX //int型裡面最大的數 using namespace std ; int n , m ; //頂點數,邊數; int Map[550][550] ; //存放點與點之間的權值; int vis[550] ; //點的訪問情況 ; int money[550][550] ; //存放點與點之間的過路費 ; void Dijkstra(int n , int v0, int vn) { int dist[550] ; //存放v0到vn的最短路徑 ; int mon[550] ; for(int i=0;i<n;i++) { dist[i] = Map[v0][i] ; //每個點的最短路徑都設為與起點相連邊上的權值,(不與起點相連的點dist[]陣列的值為MAX) mon[i] = money[v0][i] ;//每個點的過路費都初始化成與起點v0相連邊上的費用。 } vis[v0] = 1 ; //---->| dist[v0] = 0 ; // |---->對起點的初始化。 mon[v0] = 0 ; //----->| for(int i=1;i<n;i++) //除了起點一共n-1個點 ; { int MIN = MAX ; //先取一個無窮大的數,可以方便以後的替換其他的值; int k = v0 ; //記錄最短路徑相關點的下標; for(int j=0 ; j<n ; j++) //找出與起始點相連最短的路徑; { if(vis[j]==0&&dist[j]<MIN) //如果這個點沒有被訪問過,而且這個點的最短路徑比min小;(這個迴圈的作用是找出與起點v0相連的點所形成的邊,那個邊的權值最小(最短路徑最短)) { MIN = dist[j] ; k = j ; } } vis[k] = 1 ; //改變相關點訪問狀態; int j ; for(j=0;j<n;j++) { if(vis[j]==0&&Map[k][j]<MAX) //如果這個點沒被訪問過。而且這個點j與點k之間存在邊的話(Map[k][j]<MAX意思是k,j之間有邊連線) { if(Map[k][j]+dist[k]<dist[j]) //這個點與k點的路徑+起點v0到k的最短路徑 < 起點v0到j的最短路徑 { dist[j] = Map[k][j] + dist[k] ; mon[j] = mon[j] + money[k][j] ; } else if(dist[k]+Map[k][j]==dist[j]&&mon[k]+money[k][j]<mon[j]) //路徑相同,錢不同 ; { mon[j] = mon[j] + Map[k][j] ; } } } } printf("%d %d\n",dist[vn],mon[vn]) ; } int main() { int t ; scanf("%d",&t) ; while(t--) { int v0 , vn ; scanf("%d %d %d %d",&n,&m,&v0,&vn); int i , j ; for(i=0;i<n;i++) { for(j=0;j<n;j++) { if(i==j) Map[i][j] = 0 ; else Map[i][j] = MAX ; } } memset(vis,0,sizeof(vis)) ; int u , v , t , s ; for(i=0;i<m;i++) { scanf("%d %d %d %d",&u,&v,&t,&s); Map[u][v] = Map[v][u] = t ; money[u][v] = money[v][u] = s ; } Dijkstra(n,v0,vn) ; } return 0 ; }