Qrafda zirvələrin sayı çoxdur, buna görə Deykstra alqoritmasini implementasiya etmək üçün prioritet sıra istifadə edək.
Nümunə
Nümunədə verilən qraf aşağıdakı kimidir:
Alqoritmanın reallaşdırılması
Nəticəsiz dəyəri üçün sabit elan edək.
#define INF 0x3F3F3F3FÇəkiyə malik qrafı saxlamaq üçün strukturu elan edək. Hər bir elementi (zirvə, məsafə) cütləşmələri siyahısıdır.
vector<vector<pair<int, int> > > g;Dijkstra funksiyası Deykstra alqoritmasını zirvəsindən başlayır.
void Dijkstra(vector<vector<pair<int, int>>>& g, vector<int>& d,
int start)
{Prioritet sıranı elan edək və inicializasiya edək. Bu sıranın elementləri (mənbədən zirvəyə qədər məsafə, zirvə) cütü olacaqdır. Bu şəkildə, sıranın başında həmişə mənbədən ən qısa məsafədə olan zirvə olacaqdır.
priority_queue<pair<int, int>, vector<pair<int, int>>,
greater<pair<int, int>>> pq;
pq.push({0, start});Ən qısa məsafələrin massivini inicializasiya edək. Qrafın zirvələri -dən -ə qədər nömrələnir.
d = vector<int>(n + 1, INF);
d[start] = 0;Deykstra alqoritmasını sıranı boş deyilənə qədər davam etdiririk.
while (!pq.empty())
{Prioritet sıranın başından cütünü çıxardırıq.
pair<int, int> e = pq.top(); pq.pop();
int v = e.second; // nodeZirvənin saxta olub-olmadığını yoxlayırıq. Əgər -yə olan məsafə artıq hesablanmış dəyərindən böyükdürsə, bu zirvəni nəzərə almırıq.
if (e.first > d[v]) continue; // distance > d[v]ilə qonşu olan bütün zirvələri -dən keçiririk. -dən -ya olan məsafə -a bərabərdir.
for (auto edge: g[v])
{
int to = edge.first;
int cost = edge.second;Əgər (v, to) tərəfi rahatlaşırsa, dəyərini yenidən hesablayırıq və (d[to], to) cütünü sıraya əlavə edirik.
if (d[v] + cost < d[to])
{
d[to] = d[v] + cost;
pq.push({d[to], to});
}
}
}
}Proqramın əsas hissəsi. Giriş məlumatlarını oxuyuruq.
scanf("%d %d %d %d", &n, &m, &start, &fin);
g.resize(n + 1);
for (i = 0; i < m; i++)
{qeyri- yönlü və çəkidə tərəf oxuyuruq və onu qrafına əlavə edirik.
scanf("%d %d %d", &b, &e, &w);
g[b].push_back({e, w});
g[e].push_back({b, w});
}Başlanğıc zirvədən Deykstra alqoritmasını işə salırıq.
Dijkstra(g, dist, start);İstənilən ən qısa yolu dist[fin] çap edirik. Əgər dist[fin] nəticəsiz dəyərə bərabərsə, istənilən yol yoxdur deməkdir.
if (dist[fin] == INF)
printf("-1\n");
else
printf("%d\n", dist[fin]);Alqoritmanın reallaşdırılması — edge strukturu
Nəticəsiz dəyəri üçün sabit elan edək.
#define INF 0x3F3F3F3FƏn qısa məsafələr massivi elan edək.
vector<int> dist;strukturu tərəf haqqında məlumatları saxlayır: zirvəsi və onun çəkisi.
struct edge
{
int node, dist;
edge(int node, int dist) : node(node), dist(dist) {}
};strukturu həmçinin prioritet sırada istifadə ediləcəkdir. Sıra qrafın zirvələrini saxlayır, burada
— zirvənin nömrəsi;
— başlanğıc zirvədən zirvəsinə qədərki cari məsafədir.
Sıranın başında həmişə qrafın dəyəri ən az olan zirvəsi olacaqdır.
bool operator< (edge a, edge b)
{
return a.dist > b.dist;
}Qrafın qonşuluq siyahısı elan edək.
vector<vector<edge> > g;Dijkstra funksiyası Deykstra alqoritmasını zirvəsindən başlayır.
void Dijkstra(vector<vector<edge> > &g, vector<int> &d, int start)
{Prioritet sıranı elan edək və inicializasiya edək. Bu sıranın elementləri (mənbədən zirvəyə qədər məsafə, zirvə) cütü olacaqdır. Bu şəkildə, sıranın başında həmişə mənbədən ən qısa məsafədə olan zirvə olacaqdır.
priority_queue<edge> pq;
pq.push(edge(start, 0));Ən qısa məsafələrin massivini inicializasiya edək. Qrafın zirvələri -dən -ə qədər nömrələnir.
d = vector<int>(n + 1, INF);
d[start] = 0;Deykstra alqoritmasını sıranı boş deyilənə qədər davam etdiririk.
while (!pq.empty())
{Prioritet sıranın başından cütünü çıxardırıq.
edge e = pq.top(); pq.pop();
int v = e.node;Zirvənin saxta olub-olmadığını yoxlayırıq. Əgər -yə olan məsafə artıq hesablanmış dəyərindən böyükdürsə, bu zirvəni nəzərə almırıq.
if (e.dist > d[v]) continue;ilə qonşu olan bütün zirvələri -dən keçiririk. -dən -ya olan məsafə -a bərabərdir.
for (auto ed : g[v])
{
int to = ed.node;
int cost = ed.dist;Əgər (v, to) tərəfi rahatlaşırsa, dəyərini yenidən hesablayırıq və (d[to], to) cütünü sıraya əlavə edirik.
if (d[v] + cost < d[to])
{
d[to] = d[v] + cost;
pq.push(edge(to, d[to]));
}
}
}
}Proqramın əsas hissəsi. Giriş məlumatlarını oxuyuruq.
scanf("%d %d %d %d", &n, &m, &start, &fin);
g.resize(n + 1);
for (i = 0; i < m; i++)
{qeyri- yönlü və çəkidə tərəf oxuyuruq və onu qrafına əlavə edirik.
scanf("%d %d %d", &b, &e, &w);
g[b].push_back(edge(e, w));
g[e].push_back(edge(b, w));
}Başlanğıc zirvədən Deykstra alqoritmasını işə salırıq.
Dijkstra(g, dist, start);İstənilən ən qısa yolu dist[fin] çap edirik. Əgər dist[fin] nəticəsiz dəyərə bərabərsə, istənilən yol yoxdur deməkdir.
if (dist[fin] == INF)
printf("-1\n");
else
printf("%d\n", dist[fin]);Java implementasiyası
import java.util.*;
class Node implements Comparator<Node>
{
public int node, dist;
Node() {}
Node(int node, int dist)
{
this.node = node;
this.dist = dist;
}
@Override
public int compare(Node a, Node b)
{
return a.dist - b.dist;
}
};
public class Main
{
// Tərəflərin qonşuluq siyahı formasında təqdimatı
static List<List<Node> > g;
static int dist[];
static int INF = Integer.MAX_VALUE;
static int n, m;
static void dijkstra(int start)
{
PriorityQueue<Node> pq = new PriorityQueue<Node>(n+1, new Node());
for (int i = 0; i <= n; i++)
dist[i] = Integer.MAX_VALUE;
// Prioritet sıraya mənbə zirvəni əlavə edək
pq.add(new Node(start, 0));
// Mənbəyə məsafə 0-a bərabərdir
dist[start] = 0;
while(!pq.isEmpty())
{
Node e = pq.poll();
int v = e.node;
if (e.dist > dist[v]) continue;
for(int j = 0; j < g.get(v).size(); j++)
{
int to = g.get(v).get(j).node;
int cost = g.get(v).get(j).dist;
if (dist[v] + cost < dist[to])
{
dist[to] = dist[v] + cost;
pq.add(new Node(to,dist[to]));
}
}
}
}
public static void main(String[] args)
{
Scanner con = new Scanner(System.in);
n = con.nextInt();
m = con.nextInt();
int start = con.nextInt();
int fin = con.nextInt();
g = new ArrayList<List<Node> >();
// Hər bir zirvə üçün siyahı inizializasiya edək
for (int i = 0; i <= n; i++)
{
List<Node> item = new ArrayList<Node>();
g.add(item);
}
for(int i = 0; i < m; i++)
{
int b = con.nextInt();
int e = con.nextInt();
int w = con.nextInt();
g.get(b).add(new Node(e,w));
g.get(e).add(new Node(b,w));
}
dist = new int[n+1];
dijkstra(start);
if (dist[fin] == INF)
System.out.println(-1);
else
System.out.println(dist[fin]);
con.close();
}
}Python implementasiyası
Prioritet sıranı import edirik.
from queue import PriorityQueuesabitini elan edək.
INF = 10**9Dijkstra funksiyası Deykstra alqoritmasını zirvəsindən başlayır.
def dijkstra(graph, dist, start):Prioritet sıranı elan edək və inicializasiya edək. Bu sıranın elementləri (mənbədən zirvəyə qədər məsafə, zirvə) cütü olacaqdır. Bu şəkildə, sıranın başında həmişə mənbədən ən qısa məsafədə olan zirvə olacaqdır.
pq = PriorityQueue()
pq.put((0, start))Ən qısa məsafələrin siyahısını inicializasiya edək. Qrafın zirvələri -dən -ə qədər nömrələnir.
dist.extend([INF] * (n + 1))
dist[start] = 0Deykstra alqoritmasını sıranı boş deyilənə qədər davam etdiririk.
while not pq.empty():Prioritet sıranın başından (cur_dist, v) cütünü çıxardırıq.
cur_dist, v = pq.get()Zirvənin saxta olub-olmadığını yoxlayırıq. Əgər -yə olan məsafə artıq hesablanmış dist[v] dəyərindən böyükdürsə, bu zirvəni nəzərə almırıq.
if cur_dist > dist[v]: continueilə qonşu olan bütün zirvələri -dən keçiririk. -dən -ya olan məsafə -a bərabərdir.
for to, cost in graph[v]:Əgər (v, to) tərəfi rahatlaşırsa, dəyərini yenidən hesablayırıq və (dist[to], to) cütünü sıraya əlavə edirik.
if dist[v] + cost < dist[to]:
dist[to] = dist[v] + cost
pq.put((dist[to], to))Proqramın əsas hissəsi. Giriş məlumatlarını oxuyuruq.
n, m = map(int, input().split())
start, fin = map(int, input().split())
g = [[] for _ in range(n + 1)]
for _ in range(m):qeyri- yönlü və çəkidə tərəf oxuyuruq və onu qrafına əlavə edirik.
b, e, w = map(int, input().split())
g[b].append((e, w))
g[e].append((b, w))Ən qısa məsafələrin siyahısını inicializasiya edirik.
dist = []Başlanğıc zirvədən Deykstra alqoritmasını işə salırıq.
dijkstra(g, dist, start)İstənilən ən qısa yolu dist[fin] çap edirik. Əgər dist[fin] nəticəsiz dəyərə bərabərsə, istənilən yol yoxdur deməkdir.
if dist[fin] == INF:
print("-1")
else:
print(dist[fin])