İçeriğe atla
ΣDSA Patterns
Menü
Dil

En Kısa Yol (Ağırlıklı)

Rehber 5 / 6 · Yol 5 / 6

Etkileşimli

Zihinsel model

Bu problem için animasyonlu çözüm. Adımları kaydır veya boşlukla duraklat; değişmezi yüksek sesle yeniden anlat.

Adım 1 / 6
1src2dst

leave only while green

Second minimum time: n=2, bir kenar, time=3, change=2. Işıklar: change dk yeşil, sonra change dk kırmızı, t=0'da yeşil başlar.

Demo önizleme: Bu çözümler otomatik test paketini geçiyor ama insan tarafından incelenmedi. Trade-off ve yazıları taslak olarak değerlendirin.

Second Minimum Time to Reach Destination

Problem (yeniden ifade)

Düğümler 1…n üzerinde yönsüz, ağırlıksız graf. Her kenar time dakika. Her düğümde trafik ışığı: change dakika yeşil, sonra change dakika kırmızı, t=0’da yeşil başlar. Yalnızca yeşilken ayrılabilirsin (kırmızıda bekle). 1’den n’ye ikinci-minimum varış süresini döndür.

Sezgi

n’de iki farklı varış süresi gerekir, her düğüm birinci ve (kesin daha büyük) ikinci zaman tutar. Varışa göre Dijkstra/BFS. Ayrılmadan önce ⌊t / change⌋ tekse bir sonraki yeşili bekle: t += change - t % change. Sonra her komşu t + time’da varır.

Yaklaşımlar

Birinci ve ikinci varış

Doğrulanmadı
Zaman O((n+E) log n)Alan O(n+E)

Fikir. dist1[v], dist2[v]. Aday nt: nt < dist1[v] ise birinciyi ikinciye kaydır, birinciyi yaz; dist1[v] < nt < dist2[v] ise ikinciyi yaz. İkisinde de it. n’yi t > dist1[n] ile ilk pop ettiğinde o t cevap. Eşit süreler yok sayılır (“ikinci” değil).

Yürüyüş. n=2, tek kenar, time=3, change=2. 2’ye ilk varış 3. 2’den 4’e kadar bekleyip ayrıl, 1’e 7, 8’e kadar bekle, 2’ye 11.

Trade-off. Düğümü ilk ziyarette kilitleme — ikinci ziyaret asıl nokta. Bekleme kalkış zamanını kullanır; saklanan dist varış. 64-bit süre: time ve change 10^9’a gider.

Çözüm
/**
 * Toy PQ: sort + shift. Interview/production: binary heap.
 * Each node keeps first and second arrival; leave only on green.
 */
export function secondMinimum(
  n: number,
  edges: number[][],
  time: number,
  change: number,
): number {
  const adj: number[][] = Array.from({ length: n + 1 }, () => []);
  for (const [a, b] of edges) {
    adj[a]!.push(b);
    adj[b]!.push(a);
  }
  const dist1 = new Array<number>(n + 1).fill(Infinity);
  const dist2 = new Array<number>(n + 1).fill(Infinity);
  dist1[1] = 0;
  const pq: [number, number][] = [[0, 1]];
  while (pq.length) {
    pq.sort((a, b) => a[0]! - b[0]!);
    let [t, u] = pq.shift()!;
    if (u === n && t > dist1[n]!) return t;
    if (Math.floor(t / change) % 2 === 1) t += change - (t % change);
    for (const v of adj[u]!) {
      const nt = t + time;
      if (nt < dist1[v]!) {
        dist2[v] = dist1[v]!;
        dist1[v] = nt;
        pq.push([nt, v]);
      } else if (nt > dist1[v]! && nt < dist2[v]!) {
        dist2[v] = nt;
        pq.push([nt, v]);
      }
    }
  }
  return dist2[n]!;
}
/**
 * Toy PQ: sort + shift. Interview/production: binary heap.
 * Each node keeps first and second arrival; leave only on green.
 */
export function secondMinimum(
  n: number,
  edges: number[][],
  time: number,
  change: number,
): number {
  const adj: number[][] = Array.from({ length: n + 1 }, () => []);
  for (const [a, b] of edges) {
    adj[a]!.push(b);
    adj[b]!.push(a);
  }
  const dist1 = new Array<number>(n + 1).fill(Infinity);
  const dist2 = new Array<number>(n + 1).fill(Infinity);
  dist1[1] = 0;
  const pq: [number, number][] = [[0, 1]];
  while (pq.length) {
    pq.sort((a, b) => a[0]! - b[0]!);
    let [t, u] = pq.shift()!;
    if (u === n && t > dist1[n]!) return t;
    if (Math.floor(t / change) % 2 === 1) t += change - (t % change);
    for (const v of adj[u]!) {
      const nt = t + time;
      if (nt < dist1[v]!) {
        dist2[v] = dist1[v]!;
        dist1[v] = nt;
        pq.push([nt, v]);
      } else if (nt > dist1[v]! && nt < dist2[v]!) {
        dist2[v] = nt;
        pq.push([nt, v]);
      }
    }
  }
  return dist2[n]!;
}

Şablon bağlantısı

Dijkstra + ekstra durum; burada (düğüm, k) yerine düğüm başına ikinci mesafe. LC 787 ile aynı “ilk pop’ta durma” fikri.

Yansıma