time limit:1000ms
memory limit:65536k
平面上有n個點(n<=100),每個點的座標均在-10000~10000之間。其中的一些點之間有連線。若有連線,則表示可從乙個點到達另乙個點,即兩點間有通路,通路的距離為兩點直線的距離。現在的任務是找出從一點到另一點之間的最短路徑。
輸入檔案short.in,共有n+m+3行,其中:
第一行為乙個整數n。
第2行到第n+1行(共n行),每行的兩個整數x和y,描述乙個點的座標(以乙個空格隔開)。
第n+2行為乙個整數m,表示圖中的連線個數。
此後的m行,每行描述一條連線,由兩個整數i,j組成,表示第i個點和第j個點之間有連線。
最後一行:兩個整數s和t,分別表示源點和目標點。
輸出檔案short.out僅一行,乙個實數(保留兩位小數),表示從s到t的最短路徑的長度。
500
2022
0231
5121
3142
5351
5
3.41
用floyd(弗洛伊德)演算法,是最簡單的最短路徑演算法,可以計算圖中任意兩點間的最短路徑。floyd的時間複雜度是o (n3),適用於出現負邊權的情況。
演算法描述:
初始化:點u、v如果有邊相連,則dis[u][v]=w[u][v]。
如果不相連則dis[u][v]=0x7fffffff
for (k =
1; k <= n; k++
) for (i =
1; i <= n; i++
) for (j =
1; j <= n; j++
) if (
(i != j)
&&(i != k)
&&(j != k)
&&(dis[i]
[j]>dis[i]
[k]+ dis[k]
[j])
) dis[i]
[j]= dis[i]
[k]+ dis[k]
[j];
演算法結束:dis[i][j]得出的就是從i到j的最短路徑。
演算法分析&思想講解:
三層迴圈,第一層迴圈中間點k,第二第三層迴圈起點終點i、j,演算法的思想很容易理解:如果點i到點k的距離加上點k到點j的距離小於原先點i到點j的距離,那麼就用這個更短的路徑長度來更新原先點i到點j的距離。
在上圖中,因為dis[1][3]+dis[3][2]3)。
用來計算從乙個點到其他所有點的最短路徑的演算法,是一種單源最短路徑演算法。也就是說,只能計算起點只有乙個的情況。
dijkstra的時間複雜度是o (n2),它不能處理存在負邊權的情況。
演算法描述:
設起點為s,dis[v]表示從s到v的最短路徑,pre[v]為v的前驅節點,用來輸出路徑。
a)初始化:dis[v]=∞(v≠s); dis[s]=0; pre[s]=0;
b)for (i = 1; i <= n ; i++)
1.在沒有被訪問過的點中找乙個頂點u使得dis[u]是最小的。
2.u標記為已確定最短路徑
3.for 與u相連的每個未確定最短路徑的頂點v
if (dis[u]+w[u][v] < dis[v])
c)演算法結束:dis[v]為s到v的最短距離;pre[v]為v的前驅節點,用來輸出路徑。
演算法分析&思想講解:
從起點到乙個點的最短路徑一定會經過至少乙個「中轉點」(例如下圖1到5的最短路徑,中轉點是2。特殊地,我們認為起點1也是乙個「中轉點」)。顯而易見,如果我們想求出起點到乙個點的最短路徑,那我們必然要先求出中轉點的最短路徑(例如我們必須先求出點2 的最短路徑後,才能求出從起點到5的最短路徑)。
換句話說,如果起點1到某一點v0的最短路徑要經過中轉點vi,那麼中轉點vi一定是先於v0被確定了最短路徑的點。
我們把點分為兩類,一類是已確定最短路徑的點,稱為「白點」,另一類是未確定最短路徑的點,稱為「藍點」。如果我們要求出乙個點的最短路徑,就是把這個點由藍點變為白點。從起點到藍點的最短路徑上的中轉點在這個時刻只能是白點。
dijkstra的演算法思想,就是一開始將起點到起點的距離標記為0,而後進行n次迴圈,每次找出乙個到起點距離dis[u]最短的點u,將它從藍點變為白點。隨後列舉所有的藍點vi,如果以此白點為中轉到達藍點vi的路徑dis[u]+w[u][vi]更短的話,這將它作為vi的「更短路徑」dis[vi](此時還不確定是不是vi的最短路徑)。
就這樣,我們每找到乙個白點,就嘗試著用它修改其他所有的藍點。中轉點先於終點變成白點,故每乙個終點一定能夠被它的最後乙個中轉點所修改,而求得最短路徑。
簡稱ford(福特)演算法,同樣是用來計算從乙個點到其他所有點的最短路徑的演算法,也是一種單源最短路徑演算法。
能夠處理存在負邊權的情況,但無法處理存在負權迴路的情況(下文會有詳細說明)。
演算法時間複雜度:o(ne),n是頂點數,e是邊數。
演算法實現:
設s為起點,dis[v]即為s到v的最短距離,pre[v]為v前驅。w[j]是邊j的長度,且j連線u、v。
初始化:dis[s]=0,dis[v]=∞(v≠s),pre[s]=0
for (i = 1; i <= n-1; i++)
for (j = 1; j <= e; j++) //注意要列舉所有邊,不能列舉點。
if (dis[u]+w[j]演算法分析&思想講解:
bellman-ford演算法的思想很簡單。一開始認為起點是白點(dis[1]=0),每一次都列舉所有的邊,必然會有一些邊,連線著白點和藍點。因此每次都能用所有的白點去修改所有的藍點,每次迴圈也必然會有至少乙個藍點變成白點。
#include
#include
#include
#include
#include
using
namespace std;
int n,m,dx,dy;
double a[
110]
[110
],x[
110]
,y[110];
void
input()
scanf
("%d"
,&m)
;for
(i=0
;i)scanf
("%d%d"
,&dx,
&dy)
;return;}
void
floyed()
//計算最短路
intmain()
#include
#include
#include
#include
#include
using
namespace std;
int n,m,dx,dy;
double a[
110]
[110
],x[
110]
,y[110
],dis[
3010];
bool d[
3010];
void
input()
scanf
("%d"
,&m)
;for
(i=0
;i)scanf
("%d%d"
,&dx,
&dy)
;return;}
void
dij(
)//計算單源最短路
dis[dx]=0
; d[dx]=1
;for
(i=1
;i) d[w]=1
;for
(j=1
;j<=n;j++
)//鬆弛 if(
!d[j]
&&dis[w]
+a[w]
[j]) dis[j]
=dis[w]
+a[w]
[j];
}return;}
intmain()
#include
#include
#include
#include
#include
using
namespace std;
int n,m,dx,dy;
double x[
110]
,y[110
],dis[
110]
;struct jgt
b[10000];
void
input()
scanf
("%d"
,&m)
;for
(i=1
;i<=m;i++
)scanf
("%d%d"
,&dx,
&dy)
;return;}
void
ford()
//計算最短路
}return;}
intmain()
ssl1613最短路徑問題
description 平面上有n個點 n 100 每個點的座標均在 10000 10000之間。其中的一些點之間有連線。若有連線,則表示可從乙個點到達另乙個點,即兩點間有通路,通路的距離為兩點直線的距離。現在的任務是找出從一點到另一點之間的最短路徑。input 輸入檔案short.in,共有n m...
ssl1613 最短路徑問題
最短路徑問題 time limit 10000ms memory limit 65536k total submit 312 accepted 160 case time limit 1000ms description 平面上有n個點 n 100 每個點的座標均在 10000 10000之間。其中...
最短路徑問題 SSL 1613
平面上有n個點 n 100 每個點的座標均在 10000 10000之間。其中的一些點之間有連線。若有連線,則表示可從乙個點到達另乙個點,即兩點間有通路,通路的距離為兩點直線的距離。現在的任務是找出從一點到另一點之間的最短路徑。輸入檔案short.in,共有n m 3行,其中 第一行為乙個整數n。第...