1. 程式人生 > >51nod_1459 最短路 dijkstra 特調參數

51nod_1459 最短路 dijkstra 特調參數

return == false 心算 void log con pan tdi

好多基礎知識都沒補完,只好看到、用到一個趕緊補全一個,並且保證下次需要的時候直接用,不用回來再補;

其實這個算法是在補同余最短路的時候用到的,當時突然發現理解算法導論上的原理甚至有效性證明,但是就是沒辦法寫出來合適的代碼。。於是到處尋找可以用來試驗最短路徑算法的試驗場(當時學矩陣快速米的時候也是找了51nod上面的一到基礎題作為測試的)來熟悉和不全最短路相關基礎知識。

首先是DIJKSTRA

對於DIJKSTRA首先是個貪心算法,每次從集合中選擇一條沒有走過的最短路徑來作為新的邊,到達新的節點。在以當前找到的這條邊更新所有可達的邊——所謂的松弛操作。

可以證明,在n次這樣的松弛操作之後,可以求得單元最短路(具體證明見算法導論)

這題的要求比單元最短路相對更高些,他要求找到最短路且權重最高的路徑。因而應當在每次進行松弛操作時進行更新——當且僅當路徑長度相同時選擇更大的權重,其他時候選擇更短的邊的權重。

DIJKSTRA如下:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const long long INF=1e12+233;
 5 const long long MAXN=1e3+233;
 6 long long dp[MAXN];
 7 long long point[MAXN];
 8 long long mon[MAXN];
9 long long path[MAXN][MAXN]; 10 long long n,m,start,end; 11 12 void init() 13 { 14 cin>>n>>m>>start>>end; 15 memset(mon,0,sizeof(mon)); 16 for(int i=0;i<MAXN;++i) 17 for(int j=0;j<MAXN;++j)path[i][j]=INF; 18 for(int i=0;i<n;++i) 19 { 20 cin>>point[i];
21 dp[i]=INF; 22 } 23 for(int i=0;i<m;++i) 24 { 25 int a,b,p; 26 cin>>a>>b>>p; 27 path[a][b]=p; 28 path[b][a]=p; 29 } 30 } 31 int v[MAXN]; 32 void dijkstra() 33 { 34 memset(v,0,sizeof(v)); 35 int x=start; 36 mon[start]=point[start]; 37 dp[start]=0; //dijkstra初始化,應當以最起始點為0點 38 for(int i=0;i<n;++i) 39 { 40 long long mini=INF; 41 for(int j=0;j<n;++j) 42 { 43 if(!v[j]&&dp[j]<mini) 44 { 45 x=j; 46 mini=dp[j]; 47 } 48 }v[x]=1; //標記出現過的點 49 for(int j=0;j<n;++j) 50 { 51 if(!v[j]&&dp[j]>dp[x]+path[x][j]) 52 { 53 54 mon[j]=mon[x]+point[j]; 55 }if(!v[j]&&dp[j]==dp[x]+path[x][j])//註意更新時確保該點沒有被走到,否則可能出現重復更新 56 { 57 mon[j]=max(mon[j],mon[x]+point[j]); 58 } 59 60 dp[j]=min(dp[x]+path[x][j],dp[j]); 61 } 62 }cout<<dp[end]<<" "<<mon[end]<<endl; 63 } 64 int main() 65 { 66 cin.sync_with_stdio(false); 67 init(); 68 dijkstra(); 69 return 0; 70 }

51nod_1459 最短路 dijkstra 特調參數