Asosiy mazmunga o'tish

19-dars: BFS va eng qisqa yo'l

3-darajaOltin — graflar17–24 darslar

Bu darsdan keyin siz

  • BFS ni navbat bilan yozasiz
  • vaznsiz grafda eng qisqa yo’l uzunligini topasiz
  • yo’lning o’zini (uchlar ketma-ketligini) tiklaysiz

Avval qo‘lda

~6 daqiqaguruh bilanSinf xonasi

Hamma o’rnidan tursin. O’qituvchi bir o’quvchini tanlaydi — u qo’lini ko’taradi va «nol» deydi.

Keyin har bosqichda: qo’li ko’tarilganlarning yonidagi o’tirgan o’quvchilar qo’l ko’taradi va o’z raqamini aytadi — bir oldingisidan bitta ko’p. Butun sinf qo’l ko’targanda to’xtaysiz.

Nimani sezishingiz kerak

Har kimning raqami boshlang’ich o’quvchidan qancha «qadam» uzoqda ekanini bildiradi. Diqqat qiling: hech kim raqamini ikkinchi marta o’zgartirmadi — birinchi eshitilgan raqam eng kichigi bo’ldi.

Kompyuter yopiq. Bu mashq tugamaguncha kod ochilmaydi.

BFSbreadth-first search

Grafni qatlam-qatlam kezish usuli: avval boshlang’ich uchdan bir qadam uzoqdagilar, keyin ikki qadam uzoqdagilar va hokazo.

DFS chuqurlikka kirardi, BFS esa kenglikka yoyiladi. Bitta harf farq: stek o’rniga navbat.

Vaznsiz grafda eng qisqa yo’lni BFS siz ham topish mumkin: masofalarni takror-takror yaxshilab boramiz, hech narsa o’zgarmaguncha.

sekin.py
qirralar = [(1, 2), (1, 3), (2, 4), (3, 4), (4, 5)]n = 5CHEKSIZ = float("inf")masofa = [CHEKSIZ] * (n + 1)masofa[1] = 0ozgardi = Truewhile ozgardi:  ozgardi = False  for a, b in qirralar:      if masofa[a] + 1 < masofa[b]:          masofa[b] = masofa[a] + 1          ozgardi = True      if masofa[b] + 1 < masofa[a]:          masofa[a] = masofa[b] + 1          ozgardi = Trueprint(masofa[1:])

Avval o'ylang: bu kod nima chiqaradi? Ishga tushirishdan oldin yozing.

Bashorat qiling
qirralar = [(1, 2), (1, 3), (2, 4), (3, 4), (4, 5)]n = 5CHEKSIZ = float("inf")masofa = [CHEKSIZ] * (n + 1)masofa[1] = 0ozgardi = Truewhile ozgardi:  ozgardi = False  for a, b in qirralar:      if masofa[a] + 1 < masofa[b]:          masofa[b] = masofa[a] + 1          ozgardi = True      if masofa[b] + 1 < masofa[a]:          masofa[a] = masofa[b] + 1          ozgardi = Trueprint(masofa[1:])
Javobni ko'rish
[0, 1, 1, 2, 3]

Javob to'g'ri. Kamchiligi — hech qanday tartib tanlanmagani uchun barcha qirralar qayta-qayta ko'riladi.

Har o’tishda kamida bitta uch o’z yakuniy masofasini oladi, ya’ni eng yomon holatda n marta o’tish kerak. Har o’tish esa m qirrani ko’radi.

Sig‘adimi?

Bir soniyada taxminan 10⁸ oddiy amal bajariladi.

Yechimn = 1 000n = 100 000
Takror-takror yaxshilashn^210⁶sig‘adi10¹⁰sig‘maydi
BFSn1 000sig‘adi100 000sig‘adi

Yashil — yechim o‘tadi. Sariq — chegarada, konstanta va til muhim bo‘lib qoladi. Qizil — bu yechim bilan bormaydi, boshqasini qidiring.

BFS to’g’ri tartibni tanlaydi: navbatdan uch olinganda uning masofasi allaqachon yakuniy bo’ladi. Shuning uchun hech narsani qayta ko’rish kerak emas.

tez.py
from collections import dequeqoshni = {1: [2, 3], 2: [1, 4], 3: [1, 4], 4: [2, 3, 5], 5: [4]}masofa = {1: 0}navbat = deque([1])while navbat:  u = navbat.popleft()  for v in qoshni[u]:      if v not in masofa:          masofa[v] = masofa[u] + 1          navbat.append(v)print(masofa)

Avval o'ylang: bu kod nima chiqaradi? Ishga tushirishdan oldin yozing.

Bashorat qiling
from collections import dequeqoshni = {1: [2, 3], 2: [1, 4], 3: [1, 4], 4: [2, 3, 5], 5: [4]}masofa = {1: 0}navbat = deque([1])while navbat:  u = navbat.popleft()  for v in qoshni[u]:      if v not in masofa:          masofa[v] = masofa[u] + 1          navbat.append(v)print(masofa)
Javobni ko'rish
{1: 0, 2: 1, 3: 1, 4: 2, 5: 3}

Uch masofasi BIRINCHI yozilganda yakuniy bo'ladi. Shuning uchun if v not in masofa yetadi — qayta yaxshilash umuman kerak emas.

Navbat har doim masofa bo’yicha tartiblangan bo’lib qoladi: avval barcha 0-qatlam uchlari, keyin barcha 1-qatlam uchlari va hokazo.

Demak uchga birinchi marta yetib kelgan yo’l eng kam qadamlisi bo’ladi: undan qisqarog’i bo’lganda, o’sha qisqaroq yo’lning oxirgi uchi oldinroq navbatdan chiqqan va bizni oldinroq topgan bo’lardi.

Ko’p masalada uzunlik emas, yo’lning o’zi so’raladi. Buning uchun har uch uchun uni kim ochganini eslab qolish yetadi.

Avval o'ylang: bu kod nima chiqaradi? Ishga tushirishdan oldin yozing.

Bashorat qiling
from collections import dequeqoshni = {1: [2, 3], 2: [1, 4], 3: [1, 4], 4: [2, 3, 5], 5: [4]}ota = {1: None}navbat = deque([1])while navbat:  u = navbat.popleft()  for v in qoshni[u]:      if v not in ota:          ota[v] = u          navbat.append(v)yol = []u = 5while u is not None:  yol.append(u)  u = ota[u]print(yol[::-1])
Javobni ko'rish
[1, 2, 4, 5]

Yo'l oxiridan boshiga qarab yig'iladi, keyin teskari o'giriladi. ota lug'ati bir vaqtning o'zida «ko'rildimi?» belgisi vazifasini ham bajaradi.

Vizualda har uch ustidagi son — boshlang’ichdan masofa. Bir qatlam tugamaguncha keyingisi boshlanmasligini kuzating.

BFS — qatlam-qatlam tarqalish

Uch ustidagi son — A dan masofa. Bir qatlam tugamaguncha keyingisi boshlanmaydi.

BFS navbat bilan ishlaydi va grafni qatlam-qatlam kezadi; uchga birinchi yetib kelgan qatlam eng qisqa masofa bo'ladi.

Algoritmning har qadami quyidagi ro‘yxatda matn sifatida ham berilgan — vizual faqat shu qadamlarni chizadi, yangi ma’lumot qo‘shmaydi.

  1. A dan boshlaymiz, masofasi 0. Navbatda faqat A turibdi.
  2. A navbat boshidan olindi. Yangi uchlar: B, D — ularning masofasi 0 + 1 = 1.
  3. B navbat boshidan olindi. Yangi uchlar: C, E — ularning masofasi 1 + 1 = 2.
  4. D olindi, yangi qo'shni yo'q — hammasi allaqachon topilgan.
  5. C navbat boshidan olindi. Yangi uchlar: F — ularning masofasi 2 + 1 = 3.
  6. E olindi, yangi qo'shni yo'q — hammasi allaqachon topilgan.
  7. F olindi, yangi qo'shni yo'q — hammasi allaqachon topilgan.
  8. Tayyor. Har uch ustidagi son — A dan eng qisqa masofa. Bu son BIRINCHI marta yozilganda yakuniy bo'ladi va boshqa o'zgarmaydi.
ABCDEF

A dan boshlaymiz, masofasi 0. Navbatda faqat A turibdi.

Ochilgan uch0

1/8

Tuzoq — xatoni toping

19 / 40

MasalaVaznsiz grafda 1-uchdan eng qisqa masofalarni toping.

Taklif qilingan yechim

Bu javobning 2-qismi noto'g'ri. Mantiq butunlay to'g'ri, lekin list.pop(0) navbat boshidan olganda qolgan barcha elementlarni bittaga suradi. Bitta chaqiruv O(n), demak yechim O(n + m) emas, O(n²) bo'ladi. To'g'risi: deque va popleft().

Javobning qaysi qismi noto'g'ri? Bosib belgilang.

1BFS va DFS orasidagi kod farqi nima?

Javobni ko'rish

Tuzilma: DFS stek ishlatadi (oxirgi qo’shilgan birinchi chiqadi), BFS navbat (birinchi qo’shilgan birinchi chiqadi). Qolgan hammasi bir xil.

2Nega BFS masofasi bir marta yoziladi va boshqa o'zgarmaydi?

Javobni ko'rish

Navbat masofa bo’yicha tartiblangan bo’lib qoladi. Uchga birinchi yetib kelgan yo’l eng kam qadamlisi bo’ladi, chunki qisqarog’i bo’lsa u oldinroq navbatdan chiqqan bo’lardi.

3BFS vaznli grafda ishlaydimi?

Javobni ko'rish

Ishlamaydi. U qirralar sonini sanaydi, narxni emas: kam qirrali yo’l qimmatroq bo’lishi mumkin. Vaznli graf uchun Dijkstra kerak (24-dars).

4Yo'lning o'zini qanday tiklaysiz?

Javobni ko'rish

Har uch uchun uni kim ochganini (ota) saqlab boring, keyin oxirgi uchdan boshiga qarab yuring va ro’yxatni teskari o’giring.

5list.pop(0) bilan yozilgan BFS qanday xato beradi?

Javobni ko'rish

Hech qanday xato bermaydi va to’g’ri javob qaytaradi — faqat O(n²) ishlaydi va katta testda vaqt chegarasidan o’tmaydi.

Masalalar

3 ta

  • Message RouteCSES 1667o'rta

    Yo‘lning o‘zi so‘ralgan — ota lug‘atini saqlang va oxiridan tiklang.

  • LabyrinthCSES 1193o'rta

    Panjara ham graf. Yo‘lni tiklashda uchlar emas, harflar (U, D, L, R) chiqariladi.

  • MonstersCSES 1194qiyin

    Ikki BFS: avval barcha maxluqlardan bir vaqtda, keyin o‘yinchidan. Ikkinchisi birinchisidan tez bo‘lishi kerak.

Lokal mashq: mashqlar/19-eng-qisqa/ — masala matni, testlar va tekshir.py. Avval sekin.py ni o‘zingiz yozing, keyin tayyorini oching.

Topshiriq — darajangizni tanlang

Asos · 5–7-sinf — Vizual va aniq ko'rsatmali

Sinf bo’ylab «to’lqin» mashqini o’tkazing va har o’quvchining raqamini doskaga yozing. Keyin boshqa o’quvchidan boshlab takrorlang — raqamlar qanday o’zgardi?

Mustahkam · 8–9-sinf — Matnli masala, o'zingiz tuzasiz

19-eng-qisqa masalasini yeching, keyin yechimingizni o’zgartirib yo’lning o’zini ham chiqaring. Yetib bo’lmaydigan holatni unutmang.

Chuqur · 10–11-sinf — Algoritmik, chegara holatlari bilan

BFS ni ataylab list.pop(0) bilan yozing va 100 000 uchli grafda ikkala variantni o’lchang. Farq necha barobar chiqdi? Natijani 12-darsdagi bashoratingiz bilan solishtiring.

Darsni belgilash uchun JavaScript kerak. Bu progressni saqlash uchun ishlatiladi — darslikning o'zi JavaScript'siz ham to'liq o'qiladi.