最近蒟蒻的自己重新學習了一遍最短路,也算有些體會,記錄下來。
首先引入問題:在一張圖中,從某一頂點出發,沿圖的邊到達定乙個頂點所經過的路徑中,各邊權值和最小的一條路徑。
解決該問題的演算法有:dijkstra演算法,
bellman-ford
演算法,floyd
演算法和spfa
演算法介紹:dijkstra演算法是單源最短路演算法的一種,用於求出發節點到所有可達節點的最短路長度。
限制:路徑權值必須為非負數無負權迴路單源最短路
演算法思想:dijkstra演算法運用了貪心的思想,通過不斷尋找最短距離的點,用以該點為弧尾的點的邊更新其他的路徑(鬆弛)。設起點為
start
,終點為
end,
start-->end
的最短路徑只有兩種情況。
1、start--->end (從起點到終點直接為最短路徑)
2、start--->v1--->v2...--->end (從起點通過其他的點到達終點的路徑)
演算法步驟:
把頂點v分成兩組:
s:已經求出最短路徑的頂點集合
t=v-s:尚未確定最短路徑的頂點集合
1、初始時:令s= t= t
中的頂點對應的距離值若存在
,則為該邊的權值,若不存在則為
inf(正無窮)
2、從t中選取乙個距離最小的頂點
w,將該點加入集合
s中。並用該點對
t中頂點的距離進行修改:若加入
w作為中間頂點(
v0-->w-->vn),
該路徑的距離比不加入
w的路徑更短,則修改此距離值。
3、重複上述步驟,知道s中包含所有頂點,即
s=v為止
演算法實現過程中需要兩個陣列
1、dist陣列記錄源點到每個點的最短路徑大小
2、vis陣列記錄該點是否已經在集合
s中(即是否已經找到到該點的最短路徑)
演算法過程(手動模擬,qaq醜字不要介意)
這裡用一道最短路的模板題來展示該演算法的**。(poj - 2387 til the cows come home)
題意:給你n個點,給出a到b的距離,a,b邊是可以互想抵達的,求1到n的最短距離。實質:n個頂點m條邊的無向圖,求1到n的最短路徑。
//鄰接矩陣存圖版本
#include#include
#include
using
namespace
std;
const
int max=1005
;const
int inf=0x3f3f3f3f
; int t,n; //
邊數 點數
int map[max][max]; //
鄰接矩陣存圖
int dist[max]; //
dist陣列存源點到各個點的最短路徑
bool vis[max]; //
標記是否找到最小值(是否在集合s中)
void dij(int
start)
dist[start]=0; //
源點到源點的值為0
int min=inf,pos; //
尋找dist陣列中最小值,並記錄其所在的點
for(int i=1;i<=n;i++)
}
vis[pos]=true; //
將該點加入集合s中
for(int j=1;j<=n;j++) //
用該點為弧尾的邊進行鬆弛操作
} } int
main()
dij(
1); //
以1為源點進行dijkstra
printf("
%d\n
",dist[n]);
}return0;
}
//鄰接表存圖
#include#include
#include
#include
using
namespace
std;
const
int max=1005
;const
int inf=0x3f3f3f3f
;int
t,n,a,b,len;
intdist[max];
bool
vis[max];
struct
point
;vector
e[max];
void dij(int
start)
dist[start]=0; //
源點到源點距離為0
intmin,pos;
for(int i=1;i<=n;i++)
}vis[pos]=true
;
for(int j=0;j//
用找到的點為弧尾的邊進行鬆弛
}}int
main()
dij(1);
printf(
"%d\n
",dist[n]);
}return0;
}
//參考:鏈式前向星存圖
#include#include
#include
using
namespace
std;
const
int maxn=4009
;const
int max=1009
; const
int inf=0x3f3f3f3f
;int head[max],cnt=0
;int
t,n,a,b,len;
intdist[max];
bool
vis[max];
struct
edgeedge[maxn];
inline
void add(int u,int v,int
w)void dij(int
start)
dist[start]=0
;
intmin,pos;
for(int i=1;i<=n;i++)
}vis[pos]=true
;
for(int i=head[pos];i!=-1;i=edge[i].next)
}}int
main()
dij(1);
printf(
"%d\n
",dist[n]);
}return0;
}
Dijkstra學習筆記 單源最短路
dijkstra是通過貪心來進行實現的。所以不能判定有負邊的圖。看一下這張圖,我們從1 11號點開始遍歷,且令dis ti dist i disti 為第i ii個點到1 11好點的最短路徑。首先我們把已知最短路的點設為長方形,未知的設為圓形即可,那麼一號點就是已知的,及dis t1 0 dist ...
最短路徑演算法(Dijkstra)學習筆記
include include using namespace std define vex 5 定義結點的個數 define maxpoint 100 double graph maxpoint 鄰接矩陣 inti,j intmain b maxpoint int d vex p vex 定義陣列...
Dijkstra 最短路徑
dijkstra 最短路徑 針對有向圖,不支援負權值 圖的相鄰矩陣表示方法,還要用到最小值堆 include include define unvisited 0 define visited 1 define infinite 9999 設定最大值 define n 5 定義圖的頂點數 using...