Dzwon.

Są ci, którzy przeczytali tę wiadomość przed tobą.
Subskrybuj odbieranie artykułów świeżych.
E-mail
Nazwa
Nazwisko
Jak chcesz przeczytać dzwonek
Bez spamu

Rozwiąż zadanie znalezienia najkrótszej ścieżki algorytmu DaEkstra.
Znajdź najkrótszą ścieżkę z X0 do X7. Liczba jest ustawiana przez elementy matrycy kosztów

Zbuduj ten wykres


Zacznijmy od elementu X0 i przypisujemy go znacznik 0, uważaj wszystkich swoich sąsiadów, ponieważ Nadal nie ma uwagi, przypisujesz im odpowiednie długości:


Wszyscy sąsiedzi X0 są brane pod uwagę, zaznaczamy go i idzie na górę X1. Sąsiedzi X0, X2, X4, ale X0 oznaczone, nie uważają tego. Dla x2: , Zostaw etykietę.

Dla x4: Wymiana etykiety. Wszyscy sąsiedzi Vertex X1 są brane pod uwagę, zaznaczamy to


Idź na górę x2. Sąsiedzi X0, X1, X3, X4, X5, X6, ale x0, X1 są oznaczone, nie uważaj ich.
Dla x3: , Zostaw etykietę.
Dla x5: Wymiana etykiety.
Dla x4: , Zostaw etykietę.
Dla x6: Wymiana etykiety.
Uważamy, że wszyscy sąsiedzi górnej części X2, zaznaczamy to.


Idź do góry X3. Jego sąsiedzi x0, x2, x6, ale x0, x2 są oznaczone, nie uważają ich.
Dla x6: , Zostaw etykietę.
Wszyscy sąsiedzi szczytu X3 są brane pod uwagę, zaznaczamy to.


Idź na górę x4. Jego sąsiedzi x1, x2, x5, x7, ale x1, x2 są zaznaczone, nie uważaj ich.
Dla x5: Wymiana etykiety.
Dla x7: Wymiana etykiety.
Wszyscy sąsiedzi szczytu X4 są brane pod uwagę, zaznaczamy to.


Idź na górę X5. Jego sąsiedzi x2, x4, x6, x7, ale x2, x4 są zaznaczone, nie uważaj ich.
Dla x6: , Zostaw etykietę.
Dla x7: , Zostaw etykietę.
Wszyscy sąsiedzi szczytu X5 są brane pod uwagę, zaznaczamy to.


Idź na górę x6. Jego sąsiedzi x2, x3, x5, x7, ale x2, x3, x5 są zaznaczone, nie uważaj ich.
Dla x7: , Zostaw etykietę.
Rozważane są wszystkie blaty X6, zaznaczamy to. I oznaczaliśmy pozostałe X7, wszystkie wierzchołki są brane pod uwagę.


Wniosek: Najkrótsza ścieżka ich X0 w X7 ma długość 101, ta ścieżka: X7-X4-X1-X0.

Algorytm Daekstra (angielski algorytm Dijkstra) jest algorytmem na wykresach, wymyślonych przez Holandia Naukowiec Edsgera Dikstroja w 1959 roku. Znajduje najkrótsze ścieżki z jednego z wierzchołków wykresu do wszystkich innych. Algorytm pracuje tylko dla wykresów bez masy ujemnej wornadzkowej.

Rozważ realizację algorytmu na przykładzie wykresu pokazanego na rysunku.

Niech musi znaleźć najkrótszą odległość od pierwszego wierzchołka do wszystkich innych.

Okręgi wskazują wierzchołki, linie - ścieżka między nimi (liczyć na RIBR). W kółkach zaznaczył liczbę wierzchołków, na krawędziach są wskazywane przez ich "cenę" - długość ścieżki. Obok każdego szczytu czerwieni oznaczał etykietę - długość najkrótszej ścieżki do tego wierzchołka wierzchołka 1.

Pierwszy krok. Rozważysz etap algorytmu Deiquistry dla naszego przykładu. Minimalna etykieta ma wierzchołek 1. Sąsiedzi to wierzchołki 2, 3 i 6.

Pierwszy z kolei wierzchołków wierzchołka 1 - Top 2, ponieważ długość ścieżki jest minimalna. Długość ścieżki do niej przez wierzchołek 1 jest równa sumie wartości znacznika wierzchołka 1 i długości krawędzi pochodzącej z pierwszego do 2, czyli 0 + 7 \u003d 7. Jest Mniej niż bieżący znacznik wierzchołka 2, nieskończoność, więc nowa etykieta jest 2 wierzchołki są 7.

Podobne działanie odbywa się z dwoma innymi sąsiadami pierwszego wierzchołka - 3 i 6..

Wszystkie szczyty wierzchołka 1 są sprawdzane. Obecna minimalna odległość od wierzchołka 1 jest uważana za ostateczny, a wersja nie podlega (co naprawdę sprawdziła E. Dyakstra po raz pierwszy). Przekroczyłem go z wykresu, aby pamiętać, że ten górny jest odwiedzany.

Drugi krok. Krok algorytmu jest powtarzany. Znów znajdziemy "najbliższe" z nieświadomiej wierzchołków. Jest to wierzchołek 2 Tagged 7.

Spróbuj ponownie, aby zmniejszyć znaki sąsiadów wybranego wierzchołka, próbując wejść do nich przez drugi wierzchołek. Sąsiedzi wierzchołków 2 są wierzchołkami 1, 3 i 4.

Pierwszy (w porządku) sąsiadem wierzchołka 2 jest wierzchołek 1. Ale jest już odwiedzany, więc nic nie robimy z pierwszym wierzchołkiem.

Następnym sąsiadem wierzchołka 2 jest wierzchołek 3, ponieważ ma minimalny znacznik z wierzchołków oznaczonych, jak nie jest odwiedzany. Jeśli pójdziesz do niego w 2, to długość takiej ścieżki będzie równa 17 (7 + 10 \u003d 17). Ale obecny znak trzeciego wierzchołka wynosi 9, a to jest mniejsze niż 17, więc etykieta nie zmienia się.

Innym sąsiadem wierzchołka 2 jest wierzchołek 4. Jeśli przejdziesz do niego przez drugą, to długość takiej ścieżki będzie równa sumie najkrótszej odległości do drugiego wierzchołka i odległość między wierzchołkami 2 i 4 , to znaczy 22 (7 + 15 \u003d 22). Od 22.<, устанавливаем метку вершины 4 равной 22.

Wszystkie szczyty wierzchołka 2 są oglądane, zamrozić odległość do niego i zaznaczamy go jako odwiedzane.

Trzeci krok. Powtarzamy etap algorytmu, wybierając wierzchołek 3. Po jego "przetwarzaniu" otrzymujemy wyniki:

Dalsze kroki. Powtarzamy krok algorytmu do pozostałych wierzchołków. Będą one odpowiednio wierzchołków 6, 4 i 5, zamów.

Zakończenie wykonania algorytmu. Algorytm kończy pracę, gdy nie można przetwarzać żadnego wierzchołka. W tym przykładzie wszystkie wierzchołki są utopione, ale pomyli się, by wierzyć, że to tak w żadnym przykładzie - niektóre wierzchołki mogą pozostać niezwiązane, jeśli nie można go zdobyć, tj. Jeśli liczba jest niejednoznaczna. Wynik algorytmu jest widoczny na ostatnim rysunku: Najkrótsza ścieżka z wierzchołka 1 do drugiego wynosi 7, do 3-9, do 4 - 20, do 5 do 20, do 6 - 11.

Wdrożenie algorytmu w różnych językach programowania:

C ++.

#Include "stdafx.h" #include Za pomocą przestrzeni nazw STD; CONST INT V \u003d 6; // algorytm DAEKSTRA VOID DIJKTRA (INT GR [V] [V], Int ST) (int Odległość [V], licznik, indeks, I, U, M \u003d ST + 1; Bool odwiedził [V]; dla (i \u003d 0; I. "< "<\u003e "; Cin \u003e\u003e Start; Dijkstra (GR, Start-1); System (" Pauza \u003e\u003e Void ");)

Pascal.

Program Dijkstraalgoritm; Używa CRT; const v \u003d 6; inf \u003d 100000; Wpisz Vektor \u003d tablica całkowitego; Var Start: Integer; Const Gr: Array of Intereger \u003d ((((((((((0, 1, 4, 0, 2, 0), (0, 0, 0, 9, 0, 0), (4, 0, 0, 7, 0, 0), (0, 9, 7, 0, 0, 2), (0, 0, 0, 0, 0, 8), (0, 0, 0, 0, 0, 0)); (Algorytm Dikstra) Procedura Dijkstra (GR: Tablica całkowita; St: Integer); Var Count, indeks, I, U, M, Min: Integer; Odległość: Vektor; Odwiedzone: tablica Boolean; Rozpocznij m: \u003d st; Dla I: \u003d 1 do V Rozpocznij odległość [I]: \u003d inf; Odwiedził [i]: \u003d false; koniec; Odległość: \u003d 0; Do liczby: \u003d 1 do V-1 rozpocznij Min: \u003d Inf; Dla I: \u003d 1 do V Do jeśli (nie odwiedzaj [i]) i (odległość [i]<=min) then begin min:=distance[i]; index:=i; end; u:=index; visited[u]:=true; for i:=1 to V do if (not visited[i]) and (GR<>0) i (odległość [U]<>inf) i (odległość [U] + gr inf wówczas writeln (m, "\u003e", ja, "\u003d", odległość [i]) inaczej Writeln (m, "\u003e", i, "\u003d", "trasa nie jest dostępna"); koniec; (Blok programu) Rozpocznij CLRSCR; Napisz ("Uruchamianie top \u003e\u003e"); Czytać (start); DIJKSTRA (GR, START); koniec.

Jawa.

Importuj java.io.bufferedreader; Importuj java.io.ioException; Import java.io.InputStreamReader; Importuj java.io.printWriter; Importuj java.util.arraylist; Importuj java.util.arrays; Importuj java.util.stringTokedizer; Rozwiązanie klasy publicznej (prywatny statyczny INF \u003d INTEGER.MAX_VALUE / 2; Prywatny Int N; // Liczba wierzchołków w ORGRAPH Int M; // Liczba łuków W ORGRAPH Private Arraylist Adj; // Lista prywatnej klasyfikacji sąsiedztwa WAGA; // Waga żebra w prywatnym brzeźwieniu używanym orgrafie; // macierz do przechowywania informacji o prywatnych dalekach Int Daleks i wierzchołków; // array do przechowywania odległości od początku Vertex // tablicę przodków wymaganych do przywrócenia najkrótszej ścieżki z prywatnej lokalizacji INT; uruchomić; // Rozpocznij górę, który szuka odległości do wszystkich innych prywatnych buforów Cin; Prywatny printwriter cout; PRYWATNY STRINTOWY PROJEKTEROWY; // Procedura uruchamiania algorytmu Daekster z rozpoczęcia VEREX Private Void Dejkstra (int S) (DILS [S] \u003d 0; // Najkrótsza odległość do początku wierzchołka wynosi 0 dla (int it \u003d 0; it< n; ++iter) { int v = -1; int distV = INF; //выбираем вершину, кратчайшее расстояние до которого еще не найдено for (int i = 0; i < n; ++i) { if (used[i]) { continue; } if (distV < dist[i]) { continue; } v = i; distV = dist[i]; } //рассматриваем все дуги, исходящие из найденной вершины for (int i = 0; i < adj[v].size(); ++i) { int u = adj[v].get(i); int weightU = weight[v].get(i); //релаксация вершины if (dist[v] + weightU < dist[u]) { dist[u] = dist[v] + weightU; pred[u] = v; } } //помечаем вершину v просмотренной, до нее найдено кратчайшее расстояние used[v] = true; } } //процедура считывания входных данных с консоли private void readData() throws IOException { cin = new BufferedReader(new InputStreamReader(System.in)); cout = new PrintWriter(System.out); tokenizer = new StringTokenizer(cin.readLine()); n = Integer.parseInt(tokenizer.nextToken()); //считываем количество вершин графа m = Integer.parseInt(tokenizer.nextToken()); //считываем количество ребер графа start = Integer.parseInt(tokenizer.nextToken()) - 1; //инициализируем списка смежности графа размерности n adj = new ArrayList[n]; for (int i = 0; i < n; ++i) { adj[i] = new ArrayList(); ) // Inicjalizacja listy, w której wagi wagi żeber \u003d nowa arraylista [n] są przechowywane; dla (int i \u003d 0; ja< n; ++i) { weight[i] = new ArrayList(); ) // Przeczytaj wykres określony przez listę krawędzi dla (int I \u003d 0; i< m; ++i) { tokenizer = new StringTokenizer(cin.readLine()); int u = Integer.parseInt(tokenizer.nextToken()); int v = Integer.parseInt(tokenizer.nextToken()); int w = Integer.parseInt(tokenizer.nextToken()); u--; v--; adj[u].add(v); weight[u].add(w); } used = new boolean[n]; Arrays.fill(used, false); pred = new int[n]; Arrays.fill(pred, -1); dist = new int[n]; Arrays.fill(dist, INF); } //процедура восстановления кратчайшего пути по массиву предком void printWay(int v) { if (v == -1) { return; } printWay(pred[v]); cout.print((v + 1) + " "); } //процедура вывода данных в консоль private void printData() throws IOException { for (int v = 0; v < n; ++v) { if (dist[v] != INF) { cout.print(dist[v] + " "); } else { cout.print("-1 "); } } cout.println(); for (int v = 0; v < n; ++v) { cout.print((v + 1) + ": "); if (dist[v] != INF) { printWay(v); } cout.println(); } cin.close(); cout.close(); } private void run() throws IOException { readData(); dejkstra(start); printData(); cin.close(); cout.close(); } public static void main(String args) throws IOException { Solution solution = new Solution(); solution.run(); } }

Inna opcja:

Importuj Java.io. *; Importuj java.util. *; Klasa publiczna Dijkstra (Prywatny statyczny końcowy wykres. Regapt.Eved Graph \u003d (nowy wykres. Regument ("A", "B", 7), nowa grafika. Nowożeńcy "A", "F", 14), nowy wykres.EGE ("B", "C", 10), nowy wykres. Nege ("B", "D", 15), nowy wykres. Regulamin ("C "," D ", 11), nowa grafika. Regument (" C "," F ", 2), nowa grafika. Nowo-" D "," E ", 6), nowa grafika (" E ", "F", 9),); Prywatny statyczny końcowy ciąg START \u003d "A"; Prywatny statyczny końcowy koniec końcowy \u003d "e"; publiczne statyczne void Główne (String Args) (Wykres G \u003d Nowy wykres); G.dijkstra (Start ); G.printpath; //g.printallpaths ();)) Wykres klasy (prywatna mapa końcowa Wykres; // mapowanie nazw wierzchołków do obiektów wierzchowych, zbudowany z zestawu krawędzi / ** jedna krawędź wykresu (publiczny końcowy ciąg V1, V2; Publiczny ostateczny Int DIL; Krawędź publiczna (String V1, String V2, Int Dist) this.v1 \u003d v1; this.v2 \u003d v2; this.dist \u003d dist;)) / ** jeden wierzchołek wykresu, wraz z mapowaniem do sąsiednich wierzchołków * / publicznych klas statycznych VERTEX implementuje porównywalne (Publiczna ostatnia nazwa ciągów; publiczny int \u003d integer.max_value; // max_value założony jako nieskończoność publiczny wierzchołek poprzedni \u003d null; publiczna ostatnia mapa Sąsiedzi \u003d Nowy Hashmap<>(); Publiczny wierzchołek (nazwa łańcucha) Prywatne puste PrintPath () (If \u003d\u003d To.Previous) (System.out.printf ("% s", to.name);) indziej, jeśli (to (ten. Out.PrintF ("% s (nieosiągniętego)", to.name);) else (this.previous.printpath (); System.out.printf ("-\u003e% s (% d)", to .dystą);)) Public INT porównajo (wierzchołek inny) (powrót Integer.comPare (dist, inny.dist);)) / ** Buduje wykres z zestawu krawędzi * / Wykres publiczny (Wykres \u003d Nowy Hashmap<>(Krawędzie.length); // Jedno przejście, aby znaleźć wszystkie wierzchołki (EDGE E: Krawędzie) (IF (! Graph.ContainsKey (E.V1)) Wykres.put (E.V1, nowy wierzchołek (E.v1)); jeśli (! Wykres. UWAGAY (E.V2)) Graph.put (E.V2, nowy wierzchołek (E.v2));) // inny przepustka ustawia sąsiednie wierzchołki dla (Graph.get (E.v1). Sąsiednie. Get (E.v2), e.dist); //graph.get (//graph.neighbours.put), e.dist); // Robić to również dla niekodnego wykresu)) / ** biegnie Dijkstra za pomocą Określone źródło VEREX * / Public Void Dijkstra (String StartName) (IF (! Graph.Containskey (StartName)) (System.err.Printf ("Wykres nie zawiera Start VertEx"% S " ; powrót;) końcowy wierzchołek źródło \u003d wykres.get (StartName); Nawigient Q \u003d nowy treeset<>(); // Ustawianie wierzchołków dla (VERTEX V: Wykres Dodaj (v);) DIJKSTRA (Q); ) / ** Wdrożenie algorytmu DIJKSTRA za pomocą sterty binarnej. * / Private Void Dijkstra (Final Nawigableset P) (Vertex U, V; While (! Q.Ipedy ()) (U \u003d Q.pollfirst (); // wierzchołek powróci źródło (pierwsza iteracja powróci źródło), jeśli (U.dist \u003d\u003d Integer.max_value) Przerwa; // możemy zignorować U (i inne pozostałe wierzchołki), ponieważ są one nieosiągalne // spójrz na odległości dla każdego sąsiada dla (map.entry A: U.neighbours.EntrySet ()) (v \u003d A.getkey (); // bliźnie w tej palety Int alternatedist \u003d U.dist + A.GetValue (); jeśli (naprzemienna< v.dist) { // shorter path to neighbour found q.remove(v); v.dist = alternateDist; v.previous = u; q.add(v); } } } } /** Prints a path from the source to the specified vertex */ public void printPath(String endName) { if (!graph.containsKey(endName)) { System.err.printf("Graph doesn"t contain end vertex \"%s\"\n", endName); return; } graph.get(endName).printPath(); System.out.println(); } /** Prints the path from the source to every vertex (output order is not guaranteed) */ public void printAllPaths() { for (Vertex v: graph.values()) { v.printPath(); System.out.println(); } } }

DO.

#Zawierać. #Zawierać. #Zawierać. // # definiuj big_example typedef struct node_t node_t, * heap_t; Typedef Strucd Edge_t Edge_t; Struct Edge_t (cel_t_t * nd; / * Cel tej krawędzi * / EDGE_T * rodzeństwo; / * dla pojedynczo połączonej listy * / int str; / * Koszt krawędzi * /); Struktura node_t (Edge_t * krawędź; / * pojedynczo połączona lista krawędzi * / node_t * Via; / *, gdzie poprzedni węzeł jest w najkrótszej ścieżce * / podwójna dist; / * odległość od początku węzła * / Char Nazwa; / * The, ER , nazwa * / inheate_idx; / * Link do pozycji sterty do aktualizacji odległości * /); / * - zarządzanie krawędzią --- * / #ifdef big_example # zdefiniuj blok_size (1024 * 32 - 1) #else # definiuj blok_size 15 #EdenSif Edge_t * Edge_root \u003d 0, * E_Next \u003d 0; / * Don "T Mind Pamięć Management Stuff, są oprócz punktu. Powiedz e_next \u003d Malloc (sizeof (Edge_t)) * / Void Add_edge (Node_t * A, Node_t * B, Double D) (IF (E_Next \u003d\u003d Edge_root) ) (Sizeof (Edge_t) * (Block_Size + 1)); Estrat_root.Sibling \u003d E_Next; e_nxt \u003d Edge_root + Block_size;) --e_nastu; E_Next-\u003e ND \u003d B; E_Next-\u003e Len \u003d D; A-\u003e Edge; A-\u003e Edge \u003d E_Next;) Void Free_edges () (dla (Edge_root; Edge_root \u003d E_Next) (E_Next \u003d Etal_Next.Sibling; Free (Edge_root);)) / * Priority Queue Stuff --- * / * Heap_t * sterty; inheap_len; void set_dist (node_t * nd, node_t * Via, podwójny d) (int i, j; / * już znałem lepszą ścieżkę * / jeśli (Nd-\u003e Via && D\u003e \u003d ND-\u003e Dist) Powrót / * Znajdź istniejący wpis sterty lub utwórz nowy * / nd-\u003e dist \u003d d; nd-\u003e via \u003d Via; i \u003d nd-\u003e heap_idx; jeśli (! I) i \u003d ++ heap_len; / * upheap * / dla (; i\u003e 1 && nd-\u003e dist< heap->dist; i \u003d j) (sterty [i] \u003d sterty [j]) -\u003e heap_idx \u003d i; Sterty [i] \u003d nd; nd-\u003e heap_idx \u003d i; ) Node_t * pop_queue () (node_t * nd, * tmp; int i, j; jeśli (! heap_len) powrót 0; / * Wyjmij element wiodący, wyciągnij tam element ogona i Downheap * / ND \u003d sterty; TMP \u003d sterty; dla (i \u003d 1; ja< heap_len && (j = i * 2) <= heap_len; i = j) { if (j < heap_len && heap[j]->dist\u003e Heap-\u003e DELL) J ++; Jeśli (sterty [j] -\u003e dist\u003e \u003d tmp-\u003e dist) przerwa; (Sterty [i] \u003d heap [j]) -\u003e heap_idx \u003d i; ) Sterty [i] \u003d tmp; Tmp-\u003e heap_idx \u003d i; Zwrócić nd; ) / * --- Dijkstra Stuff; Nieosiągalne węzły nigdy nie wypracują w kolejce --- * / void Calc_all (Node_t * Start) (Node_t * Lead; EDGE_T * E; SET_DIST (START, START, 0); While ((OLED \u003d Pop_queue ())) dla ( E \u003d Out-\u003e Edge; E; E \u003d E-\u003e Sibling) SET_DIST (E-\u003e ND, Ołów, Out-\u003e Dist + E-\u003e Len);) Void Show_Path (Node_T * ND) (IF (IF (IF (IF (IF (IF (ND-\u003e) Via \u003d\u003d ND) Printf ("% S", ND-\u003e Nazwa); else If (Nd-\u003e przez) Printf ("% s (nieosiągniętą)", ND-\u003e Nazwa); inaczej (show_path (Nd-\u003e VIA); Printf ("-\u003e% s (% g)", ND-\u003e Nazwa, ND-\u003e DIL);)) Int Main (Void) (#ifndef big_example int I; # define n_nodes ("f" - " A "+ 1) NODE_T * NODES \u003d CALLOC (sizeof (Node_t), n_nodes); dla (i \u003d 0; i< N_NODES; i++) sprintf(nodes[i].name, "%c", "a" + i); # define E(a, b, c) add_edge(nodes + (a - "a"), nodes + (b - "a"), c) E("a", "b", 7); E("a", "c", 9); E("a", "f", 14); E("b", "c", 10);E("b", "d", 15);E("c", "d", 11); E("c", "f", 2); E("d", "e", 6); E("e", "f", 9); # undef E #else /* BIG_EXAMPLE */ int i, j, c; # define N_NODES 4000 node_t *nodes = calloc(sizeof(node_t), N_NODES); for (i = 0; i < N_NODES; i++) sprintf(nodes[i].name, "%d", i + 1); /* given any pair of nodes, there"s about 50% chance they are not connected; if connected, the cost is randomly chosen between 0 and 49 (inclusive! see output for consequences) */ for (i = 0; i < N_NODES; i++) { for (j = 0; j < N_NODES; j++) { /* majority of runtime is actually spent here */ if (i == j) continue; c = rand() % 100; if (c < 50) continue; add_edge(nodes + i, nodes + j, c - 50); } } #endif heap = calloc(sizeof(heap_t), N_NODES + 1); heap_len = 0; calc_all(nodes); for (i = 0; i < N_NODES; i++) { show_path(nodes + i); putchar("\n"); } #if 0 /* real programmers don"t free memories (they use Fortran) */ free_edges(); free(heap); free(nodes); #endif return 0; }

PHP.

$ Edge, "Koszt" \u003d\u003e $ Edge); $ sąsiedzi [$ Edge] \u003d tablica ("koniec" \u003d\u003e $ Edge, "Koszt" \u003d\u003e $ Edge); ) $ vertices \u003d array_Unique ($ wierzchołków); foreach ($ wierzchołki jako $ Vertex) ($ Div [Vertux] \u003d inf; $ poprzednie [Vertex] \u003d NULL;) $ Div [$ Source] \u003d 0; $ Q \u003d $ wierzchołków; While (Count ($ Q)\u003e 0) (// Todo - znajdź szybszy sposób uzyskania minimum $ min \u003d inf; foreach ($ q jako $ Vertex) (jeśli ($ Diste [$ Vetex]< $min) { $min = $dist[$vertex]; $u = $vertex; } } $Q = array_diff($Q, array($u)); if ($dist[$u] == INF or $u == $target) { break; } if (isset($neighbours[$u])) { foreach ($neighbours[$u] as $arr) { $alt = $dist[$u] + $arr["cost"]; if ($alt < $dist[$arr["end"]]) { $dist[$arr["end"]] = $alt; $previous[$arr["end"]] = $u; } } } } $path = array(); $u = $target; while (isset($previous[$u])) { array_unshift($path, $u); $u = $previous[$u]; } array_unshift($path, $u); return $path; } $graph_array = array(array("a", "b", 7), array("a", "c", 9), array("a", "f", 14), array("b", "c", 10), array("b", "d", 15), array("c", "d", 11), array("c", "f", 2), array("d", "e", 6), array("e", "f", 9)); $path = dijkstra($graph_array, "a", "e"); echo "path is: ".implode(", ", $path)."\n";


Pyton

Z kolekcji Import Namedtuple, kolejka z PPRINT Import PPRINT jako PP INF \u003d Float ("Edge", "Start, End, Koszt" Wykres klasy (): Def __init __ (Jaźń, Krawędzie): Self. Dramiges \u003d krawędzie2 \u003d Self. Wierzchołki \u003d zestaw (suma (dla E w krawędziach2),)) DEF Dijkstra (Self, źródło, DEST): Asert Źródło w self.vertics dist \u003d (wierzchołek: inF dla wierzchołka w self.vertics) Poprzedni \u003d (wierzchołek: brak dla wierzchołek w self.verticttics) dist \u003d 0 q \u003d self.vertics.copy () sąsiedzi \u003d (wierzchołek: zestaw () dla wierzchołka w self.d.verticals) na początek, koniec, koszt w samochodzie. Krawędzie: sąsieks.add ((koniec , Koszt)) #pp (sąsiedzi), podczas gdy q: u \u003d min (q, klawisz \u003d lambda wierzchołek: dist) Q.Remove (U), jeśli dist [u] \u003d\u003d inf lub u \u003d \u003d dest: przerwa na V, koszt w sąsiedzi [U]: alt \u003d dist [u] + koszt, jeśli alt< dist[v]: # Relax (u,v,a) dist[v] = alt previous[v] = u #pp(previous) s, u = deque(), dest while previous[u]: s.pushleft(u) u = previous[u] s.pushleft(u) return s graph = Graph([("a", "b", 7), ("a", "c", 9), ("a", "f", 14), ("b", "c", 10), ("b", "d", 15), ("c", "d", 11), ("c", "f", 2), ("d", "e", 6), ("e", "f", 9)]) pp(graph.dijkstra("a", "e")) Output: ["a", "c", "d", "e"]

Wielu algorytmów wyszukiwania najkrótszych tras w kolumnie, w Habré, znalazłem opis algorytmu Floyd Warshlla. Ten algorytm znajduje najkrótszą ścieżkę między wszystkimi wierzchołkami wykresu i ich długości. W tym artykule opiszę zasadę działania algorytmu DaEkstra, który znajduje optymalne trasy i ich długość między jednym konkretnym wierzchołkiem (źródłem) a wszystkimi innymi wierzchołkami wykresu. Wadą tego algorytmu jest to, że nieprawidłowo działa, jeśli wykres ma ujemny łuk wagowy.

Na przykład, weź taką zorientowaną liczbę G:

Możemy sobie wyobrazić ten wykres w formie macierzy z:

Weź wierzchołek 1. Oznacza to, że poszukujemy najkrótszych tras z góry 1 do wierzchołków 2, 3, 4 i 5.
Ten algorytm krok po kroku przechodzi przez wszystkie wierzchołki wykresu i przypisuje im etykiety, które są znaną minimalną odległością od górnej części źródła do określonego wierzchołka. Rozważ ten algorytm na przykładzie.

Przypisujemy pierwszą górę etykiety równej 0, ponieważ ten wierzchołek jest źródłem. Reszta wierzchołków przypisuje znaczniki równe nieskończoności.

Następnie wybierz taki wierzchołek W, który ma minimalną wytwórnię (teraz jest wierzchołkiem 1) i rozważ wszystkie wierzchołki, do których z Vertex W jest ścieżką, która nie zawiera wierzchołków. Każdy z uważanych wierzchołków przypisujemy etykietę równą sumie znakowanej w i długości ścieżki z W do rozważanego wierzchołka, ale tylko wtedy, gdy wynikowa kwota jest mniejsza niż poprzednia wartość znacznika. Jeśli kwota nie jest mniejsza, pozostawiamy poprzednie etykietę niezmienioną.

Po uznaniu wszystkich wierzchołków, w których istnieje prosta ścieżka z W, wierzchołek W zaznaczamy zarówno odwiedzanych, jak i wybieramy nie odwiedzane, że ma minimalną wartość znacznika, będzie następujący wierzchołek W. w tym przypadku, Jest to wierzchołek 2 lub 5. Jeśli istnieje kilka wierzchołków z tymi samymi tagami, nie ma znaczenia, które wybieramy jako W.

Wybędziemy wierzchołek 2. Ale nie ma z niego pojedyncza ścieżka wychodząca, więc natychmiast świętujemy ten wierzchołek, jak odwiedziliśmy i przejdź do następnego wierzchołka z minimalną etykietą. Tym razem tylko wierzchołek 5 ma minimalną etykietę. Rozważ wszystkie wierzchołki, w których występują bezpośrednie ścieżki z 5, ale które nie są jeszcze oznaczone jako odwiedzane. Ponownie znajdziemy sumę szczytu wierzchołka W i ciężar żeber z W do bieżącego wierzchołka, a jeśli ta ilość jest mniejsza niż poprzednia tag, zastępujemy wartość etykiety do uzyskanej kwoty.

W oparciu o obraz, widzimy, że etykiety 3 i 4 wierzchołków były mniejsze niż, tj. Znaleziono krótszą drogę do tych wierzchołków z górnej części źródła. Następnie odnotowujemy 5th Vertex, jak odwiedził i wybierz następny wierzchołek, który ma minimalną etykietę. Powtarzamy wszystkie powyższe kroki, dopóki nie zostanie niewiastowane szczyty.

Po wykonaniu wszystkich działań otrzymujemy ten wynik:

Na podstawie którego można zbudować najkrótsze trasy. W przypadku liczby elementów, wektor ten jest równy liczbie wierzchołków w kolumnie, każdy element zawiera ostatni pośredni wierzchołek na najkrótszej ścieżce między górnym źródłem a końcowym wierzchołkiem. Na początku algorytmu wszystkie elementy wektora p są równe górnej części źródła (w naszym przypadku p \u003d (1, 1, 1, 1, 1)). Następnie, na etapie przeliczania wartość etykiety w rozważanym wierzchołku, jeśli w rozważanym znaczniku zmienia się na mniejszy, w tablicy R, piszą wartość bieżącego wierzchołka W. na przykład: 3rd Vertex miał etykietę o wartości "30", gdy W \u003d 1. Następnie, gdy W \u003d 5 znacznik 3 - zmienił się na "20", dlatego będziemy napisać wartość w wektorze p - p \u003d 5. Ponadto, gdy W \u003d 5 wartość etykiety zmieniła się w czwartym wierzchołku (była "50", stała się "40"), oznacza to, że musisz przypisać 4 element wektora p \u003d 5. W rezultacie otrzymujemy wektor p \u003d (1, 1, 5, 5, 1).

Wiedząc, że w każdym elemencie wektora P nagrał ostatni pośredni wierzchołek na drodze między źródłem a ostatecznym wierzchołkiem, możemy uzyskać najkrótszą trasę.

najkrótsza droga Dziś jest to ważne zadanie i jest używany niemal wszędzie, od znalezienia optymalnej trasy między dwoma obiektami na ziemi (na przykład najkrótszej ścieżki z domu na uniwersytet), w systemach autopilot, aby znaleźć optymalną trasę podczas transportu, Pakiet informacyjny w sieciach i T.P.

Najkrótsza ścieżka jest uważana za pomocą pewnego obiektu matematycznego o nazwie wykres. Szukaj najkrótsza droga Jest prowadzony między dwoma określonymi wierzchołkami na wykresie. Rezultatem jest ścieżka, która jest sekwencją wierzchołków i żeber, incydent do dwóch sąsiednich wierzchołków i jej długości.

Rozważ trzy najwięcej skuteczny algorytm Nośny najkrótsza droga:

  • algorytm Daekstra.;
  • Algorytm Floyda;
  • overnorn algorytmy.

Te algorytmy są łatwo wykonywane z małą liczbą wierzchołków na wykresie. Ze wzrostem ich liczby zadań wyszukiwania najkrótsza droga Kompletny.

Algorytm Daekstra.

Ten algorytm jest algorytmem na wykresach, który został wymyślony przez Holandia Naukowiec E. DyAKStroy w 1959 roku. Algorytm znajduje najkrótszą odległość od jednego z wierzchołków wykresu do wszystkich innych i działa tylko na wykresy bez żeber o negatywnej masy.

Każdy wierzchołek przypisuje się wagi - jest to waga ścieżki z początkowego wierzchołka do tego. Również każdy wierzchołek może być podświetlony. Jeśli wierzchołek jest podświetlony, ścieżka z niego do początkowego wierzchołka najkrótsza, jeśli nie, a następnie tymczasowa. Nadchodząc przez wykres, algorytm uważa drogę dla każdego wierzchołka, a jeśli okaże się najkrótszy, podkreśla górę. Waga tego wierzchołka jest ciężarem ścieżki. Dla wszystkich sąsiadów tego wierzchołka algorytm oblicza również wagę, bez żadnych okoliczności w żadnych okolicznościach. Algorytm kończy swoją pracę, osiągając ostateczny wierzchołek i ważenie najkrótsza droga Waga końcowego wierzchołka staje się.

Algorytm Daekstra.

Krok 1. Do wszystkich szczytów, z wyjątkiem pierwszego, waga przypisana jest równa nieskończoność, a pierwszy wierzchołek wynosi 0.

Krok 2. Wszystkie wierzchołki nie są podświetlone.

Krok 3. Pierwszy wierzchołek jest zadeklarowany prąd.

Krok 4. Waga wszystkich niezamieszkanych wierzchołków jest tłumaczona przez wzór: Masa niezbadanego wierzchołka jest minimalną liczbą starej masy tego wierzchołka, ilość masy prądu wierzchołka i masy krawędzi łączącej Aktualny wierzchołek z nierozróżnianym.

Krok 5. Wśród niezbędnych pików jest góra z minimalną wagą. Jeśli nie zostanie znalezione, to znaczy waga wszystkich wierzchołków jest równa nieskończoności, trasa nie istnieje. W konsekwencji wyjście. W przeciwnym razie prąd jest wynikiem wynikowym. Jest przydzielony.

Krok 6. Jeśli bieżący wierzchołek okazuje się być ostatecznym, pojawia się ścieżka, a jego waga jest masą końcowego wierzchołka.

Krok 7. Przejdź do Krok 4.

W realizacji oprogramowania algorytm Daekstra. Będziemy skonstruować zestaw wierzchołków S, dla których najkrótsze ścieżki z początkowego wierzchołka są już znane. Przy każdym kroku do set s dodaje się ten sam wierzchołek, odległość od początkowego wierzchołka jest mniejsza niż dla innych pozostałych wierzchołków. W tym przypadku użyjemy tablicy D, w której długości są rejestrowane najkrótsze ścieżki Dla każdego wierzchołka. Gdy set S zawiera wszystkie wierzchołki wykresu, a następnie tablarek D zawiera długości najkrótsze ścieżki Z początkowego wierzchołka do każdego wierzchołka.

Oprócz określonych tablic, użyjemy matrycy C C, gdzie element C jest długości krawędzi (I, J), jeśli nie ma żebra, to jego długość jest oparta na równej nieskończonej, to znaczy więcej niż jakakolwiek rzeczywista długość żebra. Właściwie matryca C jest matryca żeglarska.w którym wszystkie elementy zerowe są zastępowane nieskończonością.

Aby określić samą

Po zakończeniu turnieju sylwestrowego, sponsor postanowił wysłać prezenty $ m $ zwycięskie prezenty pocztą. Znajomość liczby uczestników $ N $ i czas dostawy poczty między działami "Ukrpochta", znajdziesz, po tym, jak minimalny czas ostatnia zwycięzców otrzyma nagrodę.

Dane wejściowe.

Pierwsza linia zawiera numery $ $ $ $: liczba uczestników turnieju $ n $, liczba nagród sponsora $ M $ oraz liczbę znanych tymczasowych czasów dostawy między niektórymi biurami $ K $. W następnym wierszu liczba uczestników, którzy zostali wskazani, są wskazane.

Dalej przychodzi $ k $ rzędy o wartości 3 $ numery z informacjami o znanych czasach dostawy między niektórymi przedziałami w formacie: $ A $ B $ $ T $, gdzie $ A $ b $ b $ - numery komorówek, $ t $ (0 Leqslant T Leqslant 365) Czas dostawy poczty między nimi. W ostatniej linii znajduje się pojedynczy numer - liczba poczty, z której sponsor wyśle \u200b\u200bnagrody. Wiadomo, że 1 $ LEQSLANT N, M, A, B LEQSLANT 365 USD.

Wynik

Jeśli wszystkie nagrody są dostarczane do uczestników - wycofać się w pierwszej linii "Dobry sponsor!", A w przyszłym czasie, po czym ostatni z zwycięzców otrzyma nagrodę. Jeśli przynajmniej jeden z uczestników może uzyskać nagrodę - wycofanie się w jedynej linii "nie jest winą sponsora ...". Wyjście zwrotne bez cytatów.

Testy

Dane wejściowe Wynik
1. 3 2 2
2 3
1 2 3
2 3 4
1
Dobry sponsor!
7
2. 5 1 4
5
1 3 2
2 3 3
4 2 5
4 5 6
1
Dobry sponsor!
16
3. 7 2 6
1 3
1 3 2
2 4 32
4 5 94
3 1 0
6 2 4
7 2 3
7
Nie jest winą sponsora ...
4. 5 2 6
1 2
3 1 1
3 4 2
2 4 3
5 1 4
4 5 5
2 3 7
2
Dobry sponsor!
6

Dzwon.

Są ci, którzy przeczytali tę wiadomość przed tobą.
Subskrybuj odbieranie artykułów świeżych.
E-mail
Nazwa
Nazwisko
Jak chcesz przeczytać dzwonek
Bez spamu