La campana.

Ci sono quelli che hanno letto questa notizia prima di te.
Iscriviti per ricevere articoli freschi.
E-mail
Nome
Cognome
Come vuoi leggere la campana
Senza spam.

Risolvi il compito di trovare il percorso più breve dell'algoritmo di Daekstra.
Trova il percorso più breve da x0 a x7. Il conteggio è impostato dagli elementi della matrice di costo

Costruire questo grafico


Iniziamo con l'elemento x0 e lo assegniamo un tag 0, considera tutti i suoi vicini, perché Non c'è ancora nessuna nota, gli assegni le lunghezze corrispondenti:


Tutti i vicini X0 sono considerati, segniamolo e andiamo in cima a x1. I suoi vicini X0, X2, X4, ma X0 hanno segnato, non considerarlo. Per x2: , Lascia l'etichetta.

Per x4: Sostituendo l'etichetta. Tutti i vicini del Vertex X1 sono considerati, lo segniamo


Vai in cima a x2. I suoi vicini X0, X1, X3, X4, X5, X6, ma X0, X1 sono contrassegnati, non considerarli.
Per x3: , Lascia l'etichetta.
Per x5: Sostituendo l'etichetta.
Per x4: , Lascia l'etichetta.
Per x6: Sostituendo l'etichetta.
Sono considerati tutti i vicini della cima del X2, lo segniamo.


Vai al top x3. I suoi vicini X0, X2, X6, ma X0, X2 sono contrassegnati, non considerarli.
Per x6: , Lascia l'etichetta.
Tutti i vicini della cima della X3 sono considerati, lo segniamo.


Vai in cima a x4. I suoi vicini X1, X2, X5, X7, ma X1, X2 sono contrassegnati, non considerarli.
Per x5: Sostituendo l'etichetta.
Per x7: Sostituendo l'etichetta.
Sono considerati tutti i vicini della cima della x4, lo segniamo.


Vai all'inizio di x5. I suoi vicini X2, X4, X6, X7, ma X2, X4 sono contrassegnati, non considerarli.
Per x6: , Lascia l'etichetta.
Per x7: , Lascia l'etichetta.
Sono considerati tutti i vicini della cima del X5, lo segniamo.


Vai in cima a x6. I suoi vicini X2, X3, X5, X7, ma X2, X3, X5 sono contrassegnati, non considerarli.
Per x7: , Lascia l'etichetta.
Sono considerati tutti i cimiti della cima della X6, lo segniamo. E abbiamo etichettato il restante X7, sono considerati tutti i vertici.


Conclusione: il percorso più breve del loro X0 in X7 ha una lunghezza di 101, questo percorso: X7-X4-X1-X0.

L'algoritmo Daekstra (algoritmo inglese di Dijkstra) è un algoritmo ai grafici, inventato dallo scienziato olandese Edsger Dikstroy nel 1959. Trova i percorsi più brevi da uno dei vertici del grafico a tutti gli altri. L'algoritmo funziona solo per i grafici senza peso negativo radim.

Considera l'esecuzione dell'algoritmo sull'esempio del grafico mostrato nella figura.

Lascia che sia necessario trovare la distanza più breve dal 1 ° Vertice a tutti gli altri.

I cerchi indicano i vertici, le linee - il percorso tra di loro (Conteggio ribr). Nei circoli contrassegnati i numeri dei vertici, sopra i bordi sono indicati dal loro "prezzo" - la lunghezza del percorso. Accanto a ciascuna parte superiore del rosso ha segnato l'etichetta - la lunghezza del percorso più breve per questo vertice del vertice 1.

Primo passo. Considera la fase dell'algoritmo Deiquistra per il nostro esempio. L'etichetta minima ha un vertice 1. I suoi vicini sono vertici 2, 3 e 6.

Il primo a sua volta dei vertici del vertice 1 - top 2, perché la lunghezza del percorso è minima. La lunghezza del percorso in esso attraverso il vertice 1 è uguale alla somma del valore del tag del vertice 1 e la lunghezza del bordo proveniente dal 1 ° a 2, cioè, 0 + 7 \u003d 7. È Meno del tag attuale del vertice 2, infinito, quindi la nuova etichetta è 2 ° i vertici sono 7.

Un'operazione simile viene eseguita con altri due vicini del 1 ° Vertice - il 3 ° e il 6 °.

Tutte le cime del vertice 1 sono controllate. La distanza minima corrente dal vertice 1 è considerata definitiva e la revisione non è soggetta a (cosa ha davvero dimostrato E. Dyakstra per la prima volta). Lo incrocio dal grafico per notare che questo top è visitato.

Secondo passo. La fase dell'algoritmo viene ripetuta. Troviamo di nuovo il "più vicino" dai vertici inconsapevoli. Questo è un vertice 2 taggato 7.

Riprova per ridurre i segni dei vicini del vertice selezionato, cercando di entrare nel 2 ° vertice. I vicini dei vertici 2 sono vertici 1, 3 e 4.

Il primo (in ordine) un vicino del vertice 2 è il vertice 1. Ma è già visitato, quindi non facciamo nulla con il primo vertice.

Il prossimo vicino del vertice 2 è Vertex 3, in quanto ha un tag minimo dai vertici contrassegnati come non visitati. Se vai ad esso in 2, la lunghezza di un tale percorso sarà uguale a 17 (7 + 10 \u003d 17). Ma il segno corrente del terzo vertice è 9, e questo è inferiore a 17, quindi l'etichetta non cambia.

Un altro vicino del Vertex 2 è il vertice 4. Se si accede al 2 °, la lunghezza del tale percorso sarà uguale alla somma della distanza più breve dal 2 ° vertice e alla distanza tra i vertici 2 e 4 , cioè, 22 (7 + 15 \u003d 22). Dal 22.<, устанавливаем метку вершины 4 равной 22.

Tutte le parti superiori del vertice 2 sono visualizzate, congelano la distanza da esso e lo segniamo come visitato.

Terzo passo. Ripetiamo la fase dell'algoritmo selezionando il vertice 3. Dopo la sua "elaborazione" otteniamo i risultati:

Ulteriori passi. Ripetiamo la fase dell'algoritmo per i vertici rimanenti. Questi saranno vertici 6, 4 e 5, rispettivamente, ordine.

Completamento dell'esecuzione dell'algoritmo. L'algoritmo termina il lavoro quando non è possibile elaborare alcun vertice. In questo esempio, tutti i vertici sono annegati, ma si sbatterà per credere che sarà così in ogni esempio - alcuni vertici possono rimanere disaccoppiati se è impossibile ottenerlo, cioè se il conteggio è inconcludente. Il risultato dell'algoritmo è visibile nell'ultima figura: il percorso più breve dal Vertex 1 al 2 ° è 7, a 3 ° - 9, fino al 4-20 20, al 5-20, al 6 - 11.

Implementazione dell'algoritmo in vari linguaggi di programmazione:

C ++.

#Include "stdafx.h" #include Usando il namespace std; Cost int V \u003d 6; // algoritmo daekstra void dijkstra (int gr [v] [v], int st) (Int Distance [v], conte, indice, i, u, m \u003d st + 1; bool visitato [v]; per (i \u003d 0; I. "< "<\u003e "; Cin \u003e\u003e Inizio; DIJKSTRA (GR, START-1); Sistema (" Pausa \u003e\u003e Void ");)

Pascal.

Programma dijkstraalgoritmo; Usa CRT; Cost v \u003d 6; inf \u003d 100000; Tipo Vektor \u003d Array of Integer; Var Inizio: Integer; Const Gr: Array di Integer \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)); (Dikstra algoritmo) Procedura Dijkstra (GR: array di Integer; ST: Integer); Var Count, Index, I, U, M, Min: Integer; Distanza: Vektor; Visitato: array di boolean; Iniziare m: \u003d st; Per i: \u003d 1 a V Inizia la distanza [I]: \u003d INF; Visitato [i]: \u003d falso; fine; Distanza: \u003d 0; Per il conteggio: \u003d 1 a V-1 Inizia Min: \u003d INF; Per i: \u003d 1 a v do se (non visitato [i]) e (distanza [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) e (distanza [u]<>iNF) e (distanza [u] + gr iNF Allora Writeln (M, "\u003e", I, "\u003d", Distanza [I]) Altro Writeln (M, "\u003e", I, "\u003d", "Itinerario non è disponibile"); fine; (Blocco del programma) inizia CLRSCR; Scrivi ("inizio top \u003e\u003e"); Leggi (inizio); Dijkstra (gr, inizio); fine.

Giava.

Importare java.io.bufferedreader; Import java.io.oeexception; Importare java.io.inputstreamReader; Import java.io.printwriter; importare java.util.arraylist; Importare java.util.arrays; Importare java.util.StringTokenizer; Soluzione di classe pubblica (Privatic Static Int Inf \u003d Integer.Max_Value / 2; Privato int n; // Numero di vertici nell'orgrafo privato int M; // Numero di archi nell'arraylist privato orgrafo Adj; // Elenco di adjaciency Arraylist privato PESO; // peso della costola nell'orgraforo privato del Boleno privato; // Un array per la memorizzazione delle informazioni relative ai disiati privati \u200b\u200bprivati \u200b\u200bpassati e sui vertici; // Array per la conservazione della distanza dal vertice di avviamento // Una matrice degli antenati necessari per ripristinare il percorso più breve dalla posizione Privata Int Pred Posizione; iniziare; // Inizio in cima, che sta cercando una distanza da tutti gli altri tamponi privati \u200b\u200bdel tampone; Printwriter privato cout; POTENZO PRIVATO STRINGTOLIZZATORIZZO; // Procedura per il lancio dell'algoritmo di Daekster dal Vertice di avvio Void privati \u200b\u200bDEJKSTRA (INT S) (Dist [S] \u003d 0; // La distanza più breve dal vertice di avvio è 0 per (int Iter \u003d 0; ITER< 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(); ) // inizializzazione dell'elenco in cui i pesi del peso delle costole \u003d nuovo arrayList [N] sono memorizzati; per (int i \u003d 0; io< n; ++i) { weight[i] = new ArrayList(); ) // Leggi il grafico specificato dall'elenco dei bordi per (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(); } }

Un'altra opzione:

Importare java.io. *; Importare java.util. *; Public Class Dijkstra (Privatic Static Final Graph.edge Graph \u003d (New Graph.edge ("A", "B", 7), nuovo graph.edge ("A", "c", 9), nuovo graph.edge ( "A", "f", 14), nuovo graph.edge ("B", "c", 10), nuovo graph.edge ("B", "d", 15), nuovo graph.edge ("c "," D ", 11), nuovo graph.edge (" c "," f ", 2), nuovo graph.edge (" D "," e ", 6), nuovo graph.edge (" E ", "F", 9),); String finale statico privato START \u003d "A"; END PRIVATO STRING FINAL STACTO \u003d "E"; PUBBLICO STATICO VOID PAIN (STRING ARGS) (Grafico G \u003d nuovo grafico); G.DIJKSTRA (Inizio ); G.PrintPath; //g.PrintallPaths ();)) Grafico della classe (mappa finale privata Grafico; // Mappatura dei nomi dei vertici agli oggetti vertice, costruiti da un set di bordi / ** un lato del grafico (stringa finale pubblica V1, V2; FINALE PUBBLICO INT DIST; Bordo pubblico (String V1, String V2, INT DIST) ( questo.v1 \u003d v1; this.v2 \u003d v2; this.dist \u003d dist;)) / ** un vertice del grafico, completo di mappature ai vertici vicini * / implementi di vertice di classe statica pubblica comparabili (Nome della stringa finale pubblica; pubblico int dist \u003d integer.max_value; // max_value presumibilmente essere infinito vertice pubblico precedente \u003d null; mappa finale pubblica vicini \u003d nuovo hashmap<>(); Vertex pubblico (nome stringa) Private Void PrintPath () (IF \u003d\u003d This.Previous) (System.out.Printf ("% s", questo.name);) altrimenti se (questo.previous \u003d\u003d null) (sistema. out.Printf ("% s (non raggiunto)", questo.name);) altro (questo.previous.printpath (); system.out.printf ("-\u003e% s (% d)", questo. .dist);))) pubblico int confronto (vertice altro) (return Integer.comPare (Dist, Altro.Dist);)) / ** Costruisce un grafico da un set di bordi * / grafico pubblico (grafico \u003d nuovo hashmap<>(Bordi.length); // Un pass per trovare tutti i vertici per (bordi E: Bordo E: Bordi) (se (! Graph.Containskey (E.V1)) graph.put (E.v1, nuovo vertice (E.V1)); IF (! Grafico. Containskey (E.v2)) graph.put (E.v2, Nuovo Vertice (E.V2));) // Un altro pass per impostare i vertici vicini per (graph.get (E.v1). Vicinatos.put (grafico. Get (E.v2), e.dist); //graph.get (//graph.neighbours.put), e.dist); // Fai anche questo per un grafico non rilevato)) / ** Runs Dijkstra usando a Vertice sorgente specificato * / Public Void Dijkstra (String StartName) (se (! Graph.ContainsKey (StartName)) (System.err.Printf ("Graph.err.Er" T non contiene Vertex \\ "% s \\" \\ n ", startName) ; ritorno;) Final Vertex Source \u003d graph.get (StartName); navigableset Q \u003d Nuovo Treveet<>(); // Vertici di impostazione per (Vertex V: graph.values \u200b\u200b()) (v.previous \u003d v \u003d\u003d sorgente? Fonte: null; v.dist \u003d v \u003d\u003d sorgente? 0: Integer.max_Value; Q. Aggiungi (v);) dijkstra (q); ) / ** Implementazione dell'algoritmo di Dijkstra utilizzando un mucchio binario. * / Privato Void Dijkstra (Final NavigableSet D) (Vertice u, v; while (! q.isempty ()) (u \u003d q.PollFirst (); // Vertex restituirà la sorgente (prima iterazione restituirà la fonte) se (u.dist \u003d\u003d integer.max_value) Break; // Possiamo ignorare u (e altri vertici rimanenti) poiché sono irraggiungibili // guarda le distanze per ogni prossimo per (mappa. A: u.neighbour.entryset ()) (v \u003d a.getkey (); // il vicino in questa Intetter Final Int Alternatedist \u003d U.Dist + A.GetValue (); IF (alternati< 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(); } } }

C.

#Includere. #Includere. #Includere. // # Definisci BIG_Example TypeDef Struct Node_t Node_t, * heap_t; TypeDef Struct Edge_T EDGE_T; STRUT EDGE_T (NODE_T * ND; / * Target di questo bordo * / Edge_t * fratello; / * per la lista singolarmente collegata * / INT STR; / * Costo del bordo * /); Struct NODE_T (EDGE_T * EDGE; / * Elenco collegato singolarmente dei bordi * / Node_t * Via; / * Dove il nodo precedente è nel percorso più corto * / doppio dist; / * Distanza dal nodo originario * / Nome char; / * The, ER , nome * / INTHEAP_IDX; / * Collegamento alla posizione del mucchio per l'aggiornamento della distanza * /); / * --- Gestione edge ---- * / #IFDEF BIG_Example # DefinE Block_size (1024 * 32 - 1) #else # Definisci Block_size 15 #endif Edge_t * Edge_root \u003d 0, * e_next \u003d 0; / * Non pensare le cose di gestione della memoria, sono oltre al punto. Premendend e_next \u003d malloc (sizeof (bordo_t)) * / void add_edge (node_t * a, node_t * b, doppio d) (se (e_next \u003d\u003d Edge_root ) (Sizeof (Edge_T) * (block_size + 1)); bordo_root.sibling \u003d e_next; e_next \u003d Edge_root + block_size; )-E_Next; E_Next-\u003e ND \u003d B; E_Next-\u003e Len \u003d D; E_Next -\u003e SIBILE \u003d A-\u003e EDGE; A-\u003e EDGE \u003d E_NEST;) Void Free_edge () (per (Edge_root; Edge_root \u003d E_Next) (E_Next \u003d EDGE_ROOT.SIBLY; GRATUITO (EDGE_ROOT);)) / * Roba della coda prioritaria --- * / Heap_t * heap; intheapp_len; void set_dist (node_t * nd, node_t * via, doppio d) (int i, j; / * già sapeva un percorso migliore * / se (nd-\u003e via && d\u003e \u003d nd-\u003e dist) ; / * Trova voce heap esistente o creare una nuova one * / nd-\u003e dist \u003d D; nd-\u003e via \u003d via; i \u003d nd-\u003e heap_idx; se (! I) i \u003d ++ heap_len; / * upheap; / * upheap * / per (; i\u003e 1 && nd-\u003e dist< heap->dist; i \u003d j) (heap [i] \u003d heap [j]) -\u003e heap_idx \u003d i; Heap [i] \u003d nd; nd-\u003e heap_idx \u003d i; ) node_t * pop_queue () (node_t * nd, * tmp; int i, j; if (! heap_len) return 0; / * Rimuovere l'elemento leader, tirare l'elemento tail e downheap * / nd \u003d heap; tmp \u003d heap; per (i \u003d 1; io< heap_len && (j = i * 2) <= heap_len; i = j) { if (j < heap_len && heap[j]->dist\u003e heap-\u003e dist) J ++; se (heap [j] -\u003e dist\u003e \u003d TMP-\u003e dist) pausa; (Heap [i] \u003d heap [j]) -\u003e heap_idx \u003d i; ) Heap [i] \u003d tmp; TMP-\u003e heap_idx \u003d i; Ritorno ND; ) / * --- roba dijkstra; Nodi irraggiungibili non entreranno mai nella coda --- * / void calc_all (node_t * avvio) (node_t * piombo; bordo_t * e; set_dist (avvia, avvia, 0); mentre ((piombo \u003d pop_queue ())) per ( E \u003d piombo-\u003e bordo; e; e \u003d e-\u003e sibling) set_dist (e-\u003e nd, piombo, piombo-\u003e dist + e-\u003e len);) void show_path (node_t * nd) (se (nd-\u003e Via \u003d\u003d ND) PrintF ("% s", nd-\u003e nome); altrimenti se (! nd-\u003e via) printf ("% s (non raggiunto)", nd-\u003e nome); altro (show_path (nd-\u003e Via); PrintF ("-\u003e% s (% g)", nd-\u003e nome, nd-\u003e dist);) int principale (vuoto) (#fndef big_examplet int i; # Define n_nodes ("f" - " un "+ 1) node_t * node \u003d calloc (sizeof (node_t), n_nodes); per (i \u003d 0; io< 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, "COSTO" \u003d\u003e $ EDGE); $ vicini [$ EDGE] \u003d Array ("End" \u003d\u003e $ EDGE, "COSTO" \u003d\u003e $ EDGE); ) $ vertici \u003d array_unique ($ vertici); foreach ($ vertices come $ verticex) ($ dist [$ vertuex] \u003d inf; $ precedente [$ vertuex] \u003d null;) $ dist [$ sorgente] \u003d 0; $ Q \u003d $ vertici; while (Count ($ q)\u003e 0) (// Todo - Trova un modo più veloce per ottenere un minimo $ min \u003d inf; foreach ($ q come $ vertuex) (se ($ disti [$ 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";


Pitone

Dalle collezioni Importa NamedTuple, coda da Pronto importazione Pronta PPRINT come PP INF \u003d Float ("Edge", "Start, End, Costo") Grafico della classe (): def __init __ (sé, bordi): sé .dges \u003d bordi2 \u003d sé. Verici \u003d set (somma (per e in bordi2),)) def dijkstra (self, fonte, dest): assert sorgente in self.vertibes dist \u003d (vertice: inf per vertice in self.vverices) Precedente \u003d (Vertex: Nessuno per Vertex in Self.vverices) dist \u003d 0 q \u003d self.vertibes.copy () vicini \u003d (Vertice: set () per vertice in self.vverices) per inizio, fine, costo in sé. Bordi: vicini di vicinato.add ((fine , Costo)) #pp (vicinato) mentre q: u \u003d min (q, key \u003d lambda vertice: dist) q.remove (u) se dist [u] \u003d\u003d inf o u \u003d \u003d dest: Break for v, costo nei vicini [u]: alt \u003d dist [u] + costo se 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"]

Dei numerosi algoritmi per la ricerca di percorsi più brevi sulla colonna, in Habré, ho trovato solo una descrizione dell'algoritmo di Floyd Warshlla. Questo algoritmo trova il percorso più breve tra tutti i vertici del grafico e la loro lunghezza. In questo articolo, descriverò il principio di funzionamento dell'algoritmo Daekstra, che trova percorsi ottimali e la loro lunghezza tra un particolare vertice (fonte) e tutti gli altri vertici del grafico. Lo svantaggio di questo algoritmo è che funzionerà in modo errato se il grafico ha un arco di peso negativo.

Ad esempio, prendere un conteggio così orientato G:

Possiamo immaginare questo grafico sotto forma di una matrice con:

Prendi un vertice 1. Ciò significa che cercheremo i percorsi più brevi dal top 1 ai vertici 2, 3, 4 e 5.
Questo algoritmo passo-passo passa attraverso tutti i vertici del grafico e assegna loro etichette, che sono una distanza minima nota dalla parte superiore della sorgente a un particolare vertice. Considera questo algoritmo sull'esempio.

Assegniamo la prima cima dell'etichetta uguale a 0, perché questo vertice è una fonte. Il resto dei vertici assegna tag uguali all'infinito.

Successivamente, scegli un tale vertice w, che ha un'etichetta minima (ora è un vertice 1) e considera tutti i vertici in cui dal vertice w è un percorso che non contiene vertici. Ciascuno dei vertici considerati assegniamo un'etichetta pari alla somma dell'etichettata w e la lunghezza del percorso da W al vertice in esame, ma solo se la quantità risultante è inferiore al valore del tag precedente. Se l'importo non è inferiore, lasciamo invariato l'etichetta precedente.

Dopo aver considerato tutti i vertici in cui ci sono un percorso rettilineo da w, il vertice w segniamo entrambi visitati e scegliamo da non ancora visitati, tale che ha il valore minimo del tag, sarà il seguente Vertex W. In questo caso, Questo è un vertice 2 o 5. Se ci sono diversi vertici con gli stessi tag, non importa quale scegliamo come W.

Sceglieremo un vertice 2. Ma non c'è un singolo percorso in uscita da esso, quindi celebriamo immediatamente questo vertice come visitato e vai al prossimo vertice con un'etichetta minima. Questa volta, solo il vertice 5 ha un'etichetta minimale. Considera tutti i vertici in cui ci sono percorsi diretti su 5, ma che non sono ancora contrassegnati come visitati. Ancora una volta troviamo la somma della parte superiore del vertice w e il peso delle costole da w al vertice corrente e, se questo importo è inferiore al tag precedente, sostituiamo il valore dell'etichetta alla quantità risultante.

Sulla base dell'immagine, possiamo vedere che le etichette dei 3 ° e 4 ° Vertici erano inferiori a, cioè è stato trovato un percorso più breve per questi vertici dalla parte superiore della fonte. Successivamente, notiamo il quinto vertice come visitato e seleziona il prossimo vertice, che ha un'etichetta minima. Ripetiamo tutti i passaggi precedenti fino a quando non ci sono vette non modifiche.

Dopo aver eseguito tutte le azioni, otteniamo questo risultato:

C'è anche un vettore P sulla base del quale è possibile costruire i percorsi più brevi. Con il numero di elementi, questo vettore è uguale al numero di vertici nella colonna, ciascun elemento contiene l'ultimo vertice intermedio sul percorso più breve tra la sorgente superiore e il vertice finale. All'inizio dell'algoritmo, tutti gli elementi del vettore P sono uguali alla parte superiore della fonte (nel nostro caso P \u003d (1, 1, 1, 1, 1)). Successivamente, allo stadio del ricalcolo, il valore dell'etichetta per il vertice in esame, se il tag in esame viene modificato in uno più piccolo, nella matrice di r, scriviamo il valore del vertice corrente W. Ad esempio: il 3 ° Vertex ha avuto un'etichetta con il valore "30", quando w \u003d 1. Successivamente, quando w \u003d 5, il tag 3 - è cambiato in "20", quindi scriveremo il valore nel vettore P - P \u003d 5. Inoltre, quando w \u003d 5, il valore dell'etichetta è cambiato nel 4 ° vertice (era "50", è diventato "40"), significa che è necessario assegnare un 4 ° elemento del vettore P \u003d 5. Di conseguenza, otteniamo il vettore P \u003d (1, 1, 5, 5, 1).

Sapendo che in ogni elemento del vettore P ha registrato l'ultimo vertice intermedio sulla strada tra la fonte e il vertice finale, possiamo ottenere il percorso più breve.

percorso più breve Oggi è un compito vitale e viene utilizzato quasi ovunque, che spazia dal trovare la rotta ottimale tra due oggetti sul terreno (ad esempio, il percorso più breve da casa all'università), nei sistemi di autopilota, per trovare il percorso ottimale durante il trasporto, Pacchetto di commutazione delle informazioni in reti e T.P.

Il percorso più breve è considerato utilizzando un determinato oggetto matematico chiamato grafico. Ricerca percorso più breve È condotto tra due vertici specificati nel grafico. Il risultato è il percorso, cioè la sequenza di vertici e costole, incidente per i due vertici vicini e la sua lunghezza.

Considerare tre la maggior parte algoritmo efficace Posa percorso più breve:

  • algoritmo Daekstra.;
  • Algoritmo floyd;
  • algoritmi overborn.

Questi algoritmi sono facilmente eseguiti con un piccolo numero di vertici nel grafico. Con un aumento del loro numero di attività di ricerca percorso più breve Completare.

Algoritmo Daekstra.

Questo algoritmo è un algoritmo sui grafici, che è stato inventato dallo scienziato olandese E. Dyakstroy nel 1959. L'algoritmo trova la distanza più breve da uno dei vertici del grafico a tutti gli altri e funziona solo per i grafici senza costole di peso negativo.

Ogni vertice è attribuito al peso - questo è il peso del percorso dal vertice iniziale a questo. Inoltre, ogni vertice può essere evidenziato. Se il vertice è evidenziato, il percorso da esso al vertice iniziale è il più breve, se non, quindi temporaneo. Venendo dal grafico, l'algoritmo considera il percorso per ogni vertice e, se risulta essere il più breve, evidenzia la cima. Il peso di questo vertice è il peso del percorso. Per tutti i vicini di questo vertice, l'algoritmo calcola anche il peso, senza circostanze che li usano in qualsiasi circostanza. L'algoritmo finisce il suo lavoro, raggiungendo il vertice finale e la pesatura percorso più breve Il peso del vertice finale diventa.

Algoritmo Daekstra.

Passaggio 1. A tutti i piani, ad eccezione del primo, il peso è assegnato un'infinito uguale e il primo vertice è 0.

Passaggio 2. Tutti i vertici non sono evidenziati.

Passaggio 3. Il primo vertice è dichiarato corrente.

Passaggio 4. Il peso di tutti i vertici non corrisposti è tradotto dalla formula: il peso del vertice non definito è il numero minimo del vecchio peso di questo vertice, la quantità del peso del vertice corrente e il peso del bordo che collega il bordo Vertice corrente con il non decisore.

Passaggio 5. Tra i picchi non definiti è un top con peso minimo. Se questo non è stato trovato, cioè il peso di tutti i vertici è uguale all'infinito, il percorso non esiste. Di conseguenza, l'uscita. Altrimenti, la corrente è la parte superiore risultante. È assegnato.

Passaggio 6. Se il vertice corrente risulta essere il finale, il percorso è stato trovato e il suo peso è il peso del vertice finale.

Passaggio 7. Vai al passaggio 4.

Nell'attuazione del software algoritmo Daekstra. Costruiremo una serie di vertici s per i quali sono già noti i percorsi più brevi del vertice iniziale. Ad ogni passaggio al set S, viene aggiunto lo stesso vertice, la distanza dal vertice iniziale è inferiore a per altri vertici rimanenti. In questo caso, useremo l'array D, in cui sono registrate le lunghezze percorsi più corti Per ogni vertice. Quando il set S contiene tutti i vertici del grafico, quindi l'array d conterrà lunghezze percorsi più corti Dal vertice iniziale a ciascun vertice.

Oltre agli array specificati, utilizzeremo la matrice C di C, dove l'elemento C è la lunghezza dei bordi (I, J), se non ci sono costine, la sua lunghezza è affidata a un'infinito uguale, cioè, cioè più di ogni lunghezza effettiva della nervatura. In realtà matrix c è matrice di navigazionein cui tutti gli elementi zero sono sostituiti con l'infinito.

Per determinare lo stesso

Al termine del torneo di Capodanno, lo sponsor ha deciso di inviare $ m $ regali vincenti per posta. Conoscere il numero di partecipanti $ N $ e il tempo di consegna della posta tra alcuni dipartimenti "Ukrpochta", trovare, dopo che cosa è il momento minimo, l'ultimo dei vincitori riceverà il suo premio.

Dati in ingresso

La prima riga contiene $ 3 $ numeri: il numero di partecipanti del torneo $ N $, il numero di premi dello sponsor di $ M $ e il numero di tempi di consegna temporanea noti tra alcuni degli uffici $ K $. Nella riga successiva, sono indicati i numeri dei partecipanti che sono stati indicati.

Successivo arriva $ k $ righe di $ 3 $ numeri ciascuno con informazioni sui tempi di consegna noti tra alcuni dei compartimenti in formato: $ A $ $ B $ $ t $, dove $ A $ e $ B $ - numeri compartimenti, $ T $ $ (0 \\ LeqSlant T \\ Leqslant 365) $ - Mail di consegna tra di loro. Nell'ultima riga c'è un numero unico: il numero dell'ufficio postale, da cui lo sponsor invierà premi. È noto che $ 1 \\ leqslant n, m, a, b \\ leqslant $ 365.

Produzione

Se tutti i premi vengono consegnati ai partecipanti - ritirare la prima riga "il buon sponsor!", E nel prossimo tempo, dopo di che l'ultimo dei vincitori riceverà il tuo premio. Se almeno uno dei partecipanti può ottenere un premio - ritirare nell'unica riga "Non è colpa dello sponsor ...". Frasi Uscita senza virgolette.

Test

Dati in ingresso Produzione
1. 3 2 2
2 3
1 2 3
2 3 4
1
Il buon sponsor!
7
2. 5 1 4
5
1 3 2
2 3 3
4 2 5
4 5 6
1
Il buon 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
Non è colpa dello sponsor ...
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
Il buon sponsor!
6

La campana.

Ci sono quelli che hanno letto questa notizia prima di te.
Iscriviti per ricevere articoli freschi.
E-mail
Nome
Cognome
Come vuoi leggere la campana
Senza spam.