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" #includePascal.
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] + grGiava.
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 orgrafoUn'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
C.
#Includere.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 |