====== الگوریتم دایکسترا ======
===== تعریف ====
الگوریتم دایکسترا راهکاری برای پیدا کردن کموزن مسیر از رأس مشخص آغاز به بقیه رئوس در گراف جهتدار و وزندار (با وزنهای مثبت) میدهد.
وزن یک مسیر در گراف وزندار برابر مجموع وزن یالهای آن است.
جهتدار نبودن یالها هم مشکلی ایجاد نمیکند و میتوان برای یالهای غیر جهتدار دو یال فرض کرد.
===== الگوریتم =====
فرض کنید
$1 \le s \le n$
که در آن رأس $s$ رأس آغاز است و فرض کنید:
$$dist(s) = 0$$
و به ازای هر $v\neq s$:
$$dist(v) = \infty$$
فرض کنید مجموعهی $T$ برابر رئوسی باشد که تا کنون کم وزنترین مسیر آنها را پیدا کردهایم. این الگوریتم در هر مرحله نزدیکترین رأس به $s$ را که تا کنون به مجموعهی $T$ اضافه نشده را انتخاب میکند (مثلا $x$) و آن را به مجموعهی $T$ اضافه میکند و فاصلهی دیگر رأسها را با توجه به فاصلهی $x$ بروز میکند.
به ازای هر رأس $v$ خارج $T$:
$$dist(v) = min\Big(dist(v), dist(x) + w(x, v)\Big)$$
که در آن $w(x, v)$ برابر وزن یال بین $x$ و $v$ است.
این الگوریتم در هر مرحله رأسی را که کوتاهترین فاصلهی آن تا $s$ پیدا شده است را به $T$ اضافه میکند. زیرا کوتاه ترین مسیر این رأس از یکی از رأسهای $T$ میگذرد که در مراحل قبلی فاصله آنها بدست آمده و دیگر رئوس را بروز کردهاند.
===== یک مثال =====
در گراف زیر، روند اجرای این الگوریتم را میتوانید مشاهده کنید
{{ :آموزش:الگوریتم:dijkstra_animation.gif |}}
=====مشکل با یالهای منفی =====
در صورت منفی بودن یالها فرض اینکه در هر مرحله رأسی که کوتاهترین مسیر آن پیدا شده اضافه میشود زیر سوال میرود. زیرا این رأس میتواند بدون استفاده از رأسهای $T$ و یالهای منفی مسیری کوتاهتر به $s$ پیدا کند.
===== پیچیدگی الگوریتم =====
به ازای هر رأس باید روند بالا را طی کنیم. یعنی دنبال آن بگردیم و همهی همسایههای آن را پیمایش کنیم. پس پیچیدگی زمانی برنامه از
$O(n \times n) = O(n^2)$
است. هر چند میتوان با استفاده از داده ساختار هرم پیادهسازی از
$O\Big(e \times lg(n)\Big)$
ارائه داد.
===== پیادهسازی اولیه =====
شبه کد:
function Dijkstra(s):
dist[s] = 0
for each vertex v in Graph: // Initializations
if v ≠ s
dist[v] = infinity
end if
end for
while Size(T) ≠ n : // The main loop
u := vertex not in T with min dist[u]
add u to T
for each neighbor v of u:
dist[v] = min(dist[v], dist[u]+w[u][v])
end for
end while
end function
===== پیادهسازی =====
#include
using namespace std;
const int MAXN = 1000 + 10;
const int INF = 1000*1000*1000;
int n, m;
int adj[MAXN][MAXN];
int w[MAXN][MAXN];
int dist[MAXN];
int mark[MAXN];
void readInput(){
cin >> n >> m;
for(int i=0; i> u >> v >> z;
adj[u][v] = 1;
w[u][v] = z;
}
}
void dijkstra(int s){
dist[s] = 0;
for(int i=0; i
===== پیادهسازی با استفاده از داده ساختار هرم =====
میتوان یافتن نزدیکترین رأس در هر مرحله را به کمک این داده ساختار انجام داد. در این صورت باید گراف را به صورت لیست مجاورت نگه داریم. که در $C++$ برای راحتی کار از $Set$ استفاده می کنیم.
#include
#include
#include
using namespace std;
const int MAXN = 1000*100 + 10;
const int INF = 1000*1000*1000;
typedef pair pii;
int n, m;
vector adj[MAXN];
vector w[MAXN];
set q;
int dist[MAXN];
void readInput(){
cin >> n >> m;
for(int i=0; i> u >> v >> z;
adj[u].push_back(v);
w[u].push_back(z);
}
}
void dijkstra(int s){
dist[s] = 0;
for(int i=0; i :: iterator it = q.begin();
int u = it->second;
q.erase(it);
for(int i=0; i
===== مسائل نمونه =====
- [[http://acm.sgu.ru/problem.php?contest=0&problem=103|مسئلهی ۱۰۳ سایت sgu]]
- [[http://wiki.inoi.ir/%D8%B3%D9%88%D8%A7%D9%84%D8%A7%D8%AA_%D8%A7%D9%84%D9%85%D9%BE%DB%8C%D8%A7%D8%AF/%D8%AF%D9%88%D8%B1%D9%87%E2%80%8C%DB%8C_%D8%AA%D8%A7%D8%A8%D8%B3%D8%AA%D8%A7%D9%86/%D8%AF%D9%88%D8%B1%D9%87%E2%80%8C%DB%8C_%DB%B2%DB%B2/%D8%B9%D9%85%D9%84%DB%8C_%D9%86%D9%87%D8%A7%DB%8C%DB%8C_%D8%B3%D9%88%D9%85/%D8%B3%D9%88%D8%A7%D9%84_%DB%B1|مسئله یک آزمون نهایی عملی سوم دورهی ۲۲ المپیاد کامپیوتر ایران]]
-
===== مراجع =====
- http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm