Kalıp #27
En Kısa Yol (Ağırlıklı)
ÖnerilenDijkstra, Bellman-Ford: ağırlıklı grafta minimum maliyet.
Ne zaman kullanılır
Kenarların ağırlığı var ve minimum maliyet/yol gerekiyorsa. Negatif olmayan ağırlıklarda Dijkstra; negatif kenar possible ise Bellman-Ford.
Tanıma ipuçları
- Ağırlıklı kenarlar
- Kaynaktan minimum maliyet / en kısa yol
- En ucuz rota / ağ gecikmesi
- Negatif ağırlıklar (Dijkstra değil, Bellman-Ford)
Yaygın tuzaklar
- Negatif kenarlarla Dijkstra kullanmak (yanlış cevap)
- Ulaşılamayan düğümleri unutmak (-1 veya INF döndür)
- Stale girişli öncelik kuyruğu (lazy deletion vs decrease-key)
90 saniyelik tanıma egzersizi
Hangisi en iyi uyuyor?
- Ağırlıklı kenarlar
- Kaynaktan minimum maliyet / en kısa yol
- En ucuz rota / ağ gecikmesi
Etkileşimli
Zihinsel model
Değişmezin tam adım adım anlatımı. Duraklat, noktalara tıkla veya ← → kullan. Her adımı kendi cümlelerinle anlatmayı hedefle.
dist[S]=0 · min-heap
Ağırlıklı en kısa yol. Kenarlar: S→A 1, S→B 4, A→B 1, A→T 7, B→T 1. BFS sıçraması yanlış metriktir.
Nasıl düşünülür
Kenarların ağırlığı olduğunda BFS (hop sayan) en kısa yolu vermez, iki hopluk ucuz kenar yolu, tek hopluk pahalı kenarı geçebilir. Dijkstra iş atıdır: dist[] dizisi ve mesafeye göre min-öncelik kuyruğu tut. En yakın ziyaret edilmemiş düğümü pop et, kenarlarını gevşet (eğer dist[u] + w < dist[v] ise dist[v]’i güncelle ve push). Her düğüm ilk pop edildiğinde kesinleşir, tekrar ziyaret gerekmez.
Kısıt: Dijkstra negatif olmayan ağırlık gerektirir. Negatif kenar, “kesinleşmiş” bir düğümün mesafesini pop sonrası düşürebilir ve greedy değişmezi bozar. Negatif kenarlar için (veya negatif döngü tespiti için) Bellman-Ford: her kenarı V-1 kez gevşet; V’inci geçiş hâlâ gevşetirse negatif döngü vardır.
Şablon şekilleri
| Şekil | Temel hamle | Örnek |
|---|---|---|
| Dijkstra | Mesafeye min-heap; pop’ta gevşet | LC 743, LC 1976 |
| Dijkstra + durum | Durum = (düğüm, ek boyut); bileşik mesafeli heap | LC 787 (k-durak), LC 2045 |
| Cevapta ikili arama + BFS | Eşikte fizibilite kontrolü | LC 1631 |
| Bellman-Ford | Tüm kenarları V-1 kez gevşet | (negatif kenar olduğunda) |
Karmaşıklık temeli
İkili heap’li Dijkstra: O((V + E) log V) zaman, O(V) alan. Bellman-Ford: O(VE) zaman, O(V) alan. Yoğun graf için heapsiz O(V²) Dijkstra daha basit ve rekabetçi olabilir.
Şablondan probleme
- Ağırlıkların negatif olmadığını doğrula; değilse Bellman-Ford’a geç.
(komşu, ağırlık)çiftlerinden komşuluk listesi kur.dist[source] = 0,(0, source)push; diğerleriInfinity.- Min’i pop et; stale ise atla (mesafe uyumsuz); komşuları gevşet.
- Döngü sonunda
dist[dest]cevaptır, hâlâInfinityise-1(ulaşılamaz). - Problem kısıt ekliyorsa (k-durak, indirim), algoritmayı değil durumu genişlet.
Şablon
TypeScript, Python ve C#’te aynı iskelet. Değişmezi uyarla; yapıyı koru.
/**
* Shortest path template: Dijkstra from a source over an adjacency list.
*
* NOTE: This uses `pq.sort + shift` as a toy priority queue for readability.
* In interviews / production, use a binary heap (O((V+E) log V)); this version
* is O(V² log V) due to the per-step sort. Algorithm and logic are identical.
*/
export function dijkstra(
n: number, edges: [number, number, number][], source: number,
): number[] {
const adj: [number, number][][] = Array.from({ length: n }, () => []);
for (const [a, b, w] of edges) {
adj[a]!.push([b, w]);
adj[b]!.push([a, w]);
}
const dist = new Array<number>(n).fill(Infinity);
dist[source] = 0;
const pq: [number, number][] = [[0, source]];
while (pq.length) {
// Toy PQ: sort + shift. Replace with a binary heap for O((V+E) log V).
pq.sort((a, b) => a[0]! - b[0]!);
const [d, u] = pq.shift()!;
if (d > dist[u]!) continue;
for (const [v, w] of adj[u]!) {
if (dist[u]! + w < dist[v]!) {
dist[v] = dist[u]! + w;
pq.push([dist[v]!, v]);
}
}
}
return dist;
}/**
* Shortest path template: Dijkstra from a source over an adjacency list.
*
* NOTE: This uses `pq.sort + shift` as a toy priority queue for readability.
* In interviews / production, use a binary heap (O((V+E) log V)); this version
* is O(V² log V) due to the per-step sort. Algorithm and logic are identical.
*/
export function dijkstra(
n: number, edges: [number, number, number][], source: number,
): number[] {
const adj: [number, number][][] = Array.from({ length: n }, () => []);
for (const [a, b, w] of edges) {
adj[a]!.push([b, w]);
adj[b]!.push([a, w]);
}
const dist = new Array<number>(n).fill(Infinity);
dist[source] = 0;
const pq: [number, number][] = [[0, source]];
while (pq.length) {
// Toy PQ: sort + shift. Replace with a binary heap for O((V+E) log V).
pq.sort((a, b) => a[0]! - b[0]!);
const [d, u] = pq.shift()!;
if (d > dist[u]!) continue;
for (const [v, w] of adj[u]!) {
if (dist[u]! + w < dist[v]!) {
dist[v] = dist[u]! + w;
pq.push([dist[v]!, v]);
}
}
}
return dist;
}- 1#743 Network Delay TimeRehbermedium
- 2#787 Cheapest Flights Within K StopsRehbermedium
- 3#1631 Path With Minimum EffortRehbermedium
- 4#1976 Number of Ways to Arrive at DestinationRehbermedium
- 5#2045 Second Minimum Time to Reach DestinationRehberhard
- 6#2093 Minimum Cost to Reach City With DiscountsRehberhard