dijkstra是通過貪心來進行實現的。所以不能判定有負邊的圖。
看一下這張圖,我們從1
11號點開始遍歷,且令dis
ti
dist_i
disti
為第i
ii個點到1
11好點的最短路徑。
首先我們把已知最短路的點設為長方形,未知的設為圓形即可,那麼一號點就是已知的,及dis
t1=0
dist_1=0
dist1
=0。接下來,從已知點集到未知點集最短的乙個點為點2
22,及dis
t2=5
dist_2=5
dist2
=5。然後一步一步推,如圖:
然後是4
44號點最近
再就是3
33號點。
這樣就可以推下去就可以了。
注意:最短的那個點並不是指邊權,比如說6
66號點,它的值是由dis
t3+c
3,6=
8dist_3+c_=8
dist3
+c3,
6=8
,不僅僅是c3,
6c_
c3,6。
#include
//採用dijstra
#include
//樸素
#include
//使用vector動態陣列儲存
#define maxn 500039
using
namespace std;
int ans[maxn]
;int n,m,s,i,j,from;
struct dif;
vector q[maxn]
;int v[maxn]
;int t,minx,a,b;
intmain()
v[s]=1
;for
(int k=
1;k) v[a]=1
; ans[a]
=minx;
}for
(int i=
1;i<=n;i++)if
(ans[i]
==0x3f3f3f3f
)printf
("2147483647 ");
else
printf
("%d "
,ans[i]);
return0;
}
這裡會發現,我們這裡有三層迴圈,大大降低了效率,所以我們需要使用堆來進行優化。
我們看一下dijkstea的步驟:
設定起點
從已知未知集中找到最短的一條路徑
更新這個點的最短路
重複24
我們發現第2步可以進行優化。
怎麼優化呢?
我會zkw非遞迴式線段樹!
我會斐波那契額堆!
我會堆!
我們把所有從已知點集到擴充套件出的所有點扔近乙個堆。當然, dis
tdist
dist
最小的在堆頂部就可以了。
#include
#include
#include
#include
#define maxn 100039
#define maxm 200039
using
namespace std;
//#define debug
typedef
int type;
inline type read()
if(flag)
return
-sum;
return sum;
}struct jtz};
priority_queue
,greater
> q;
int dist[maxn]
,vis[maxn]
,n,m,s;
int u,v,w;
int head[maxn]
,nex[maxm]
,to[maxm]
,c[maxm]
,k;#define add(x,y,z) c[++k]=z;\
to[k]=y;\
nex[k]=head[x];\
head[x]=k;
void
dij())
; dist[s]=0
;while
(!q.
empty()
));}
}return;}
intmain()
memset
(dist,
0x7f
,sizeof
(dist));
dij();
for(
int i=
1;i<=n;i++
)printf
("%d "
,dist[i]);
return0;
}
Dijkstra 單源最短路徑
演算法思想 輔助陣列dis i 表示當前源頂點到i的最短路徑。dis i 在程式未結束前,類似於動態規劃,可更新以取得最小值 陣列path用來記錄路徑 首先初始化令dis i 為edge v0 i v0為源頂點 然後選擇離源頂點最小的路徑,加入到構造最短路徑的點集合中,然後看是否可以更新dis i ...
Dijkstra 單源最短路徑
演算法思想 輔助陣列dis i 表示當前源頂點到i的最短路徑。dis i 在程式未結束前,類似於動態規劃,可更新以取得最小值 陣列path用來記錄路徑 首先初始化令dis i 為edge v0 i v0為源頂點 然後選擇離源頂點最小的路徑,加入到構造最短路徑的點集合中,然後看是否可以更新dis i ...
Dijkstra單源最短路徑
dijkstra單源最短路徑 給定乙個帶權有向圖g v,e 其中每條邊的權是乙個非負實數。另外,還給定 v 中的乙個頂點,稱為源。現在我們要計算從源到所有其他各頂點的最短路徑長度。這裡的長度是指路上各邊權之和。這個問題通常稱為單源最短路徑問題。下面給出兩個計算單源最短路徑的模板。dijkstra 簡...