23-dars: Daraxtlar
3-darajaOltin — graflar17–24 darslar
Bu darsdan keyin siz
- daraxtning ikki xossasini ayta olasiz va ulardan foyda olasiz
- ildizdan chuqurlikni, bolalardan shox o’lchamini hisoblaysiz
- rekursiyasiz, ikki yurishda ishlaydigan sxemani yozasiz
Avval qo’lda
“Avval qo’lda” bo'limiga havolaAvval qo‘lda
Oilangiz shajarasini chizing — kamida sakkiz kishi, eng yuqorida bitta bobo.
Har kishining yoniga ikkita son yozing: bobodan necha avlod pastda turibdi (chuqurlik) va uning ostida jami nechta odam bor, o’zi bilan birga (shox o’lchami).
Nimani sezishingiz kerak
Chuqurlikni yuqoridan pastga yozdingiz, shox o’lchamini esa pastdan yuqoriga — chunki otaning soni bolalarniki hisoblanmaguncha ma’lum bo’lmaydi. Ikki yo’nalish, ikki bosqich.
Kompyuter yopiq. Bu mashq tugamaguncha kod ochilmaydi.
Daraxtning ikki xossasi
“Daraxtning ikki xossasi” bo'limiga havoladaraxttree
Sikli yo’q bog’langan graf. n uchli daraxtda aynan n − 1 ta qirra
bo’ladi va har ikki uch orasida yagona yo’l mavjud.
Bu ikki xossa hayotni ancha osonlashtiradi. Halqa yo’qligi tufayli
korilgan to’plami kerak emas: qaytib ketmaslik uchun otaga
qaytmaslik yetadi. Yagona yo’l esa «eng qisqa yo’l» masalasini
yo’qotadi — yo’l bitta, u ham eng qisqasi.
Daraxtga ildiz tanlansa, har uchda aniq bitta ota va bir nechta bola paydo bo’ladi.
Sekin yechim
“Sekin yechim” bo'limiga havolaHar uch uchun uning shoxini alohida kezib chiqamiz.
n = 6qirralar = [(1, 2), (1, 3), (2, 4), (2, 5), (3, 6)]qoshni = [[] for _ in range(n + 1)]for a, b in qirralar: qoshni[a].append(b) qoshni[b].append(a)ota = [0] * (n + 1)stek = [(1, 0)]while stek: u, p = stek.pop() ota[u] = p for v in qoshni[u]: if v != p: stek.append((v, u))olcham = [0] * (n + 1)for boshi in range(1, n + 1): soni = 0 ichki = [boshi] while ichki: u = ichki.pop() soni += 1 for v in qoshni[u]: if v != ota[u]: ichki.append(v) olcham[boshi] = soniprint(olcham[1:])Avval o'ylang: bu kod nima chiqaradi? Ishga tushirishdan oldin yozing.
n = 6qirralar = [(1, 2), (1, 3), (2, 4), (2, 5), (3, 6)]qoshni = [[] for _ in range(n + 1)]for a, b in qirralar: qoshni[a].append(b) qoshni[b].append(a)ota = [0] * (n + 1)stek = [(1, 0)]while stek: u, p = stek.pop() ota[u] = p for v in qoshni[u]: if v != p: stek.append((v, u))olcham = [0] * (n + 1)for boshi in range(1, n + 1): soni = 0 ichki = [boshi] while ichki: u = ichki.pop() soni += 1 for v in qoshni[u]: if v != ota[u]: ichki.append(v) olcham[boshi] = soniprint(olcham[1:])Haqiqiy natija:
[6, 3, 2, 1, 1, 1]
Ildizning shoxi — butun daraxt. Diqqat qiling: korilgan to'plami umuman yo'q, chunki daraxtda halqa bo'lmaydi va otaga qaytmaslik yetarli.
Javobni ko'rish
[6, 3, 2, 1, 1, 1]
Ildizning shoxi — butun daraxt. Diqqat qiling: korilgan to'plami umuman yo'q, chunki daraxtda halqa bo'lmaydi va otaga qaytmaslik yetarli.
Nega sekin
“Nega sekin” bo'limiga havolaIldizga yaqin uchlar deyarli butun daraxtni qayta-qayta kezadi. Uzun
zanjir shaklidagi daraxtda ish hajmi n² ga chiqadi.
Sig‘adimi?
Bir soniyada taxminan 10⁸ oddiy amal bajariladi.
| Yechim | n = 1 000 | n = 200 000 |
|---|---|---|
Har uchdan qayta kezishn^2 | 10⁶sig‘adi | 10¹⁰sig‘maydi |
Ikki yurishn | 1 000sig‘adi | 200 000sig‘adi |
Yashil — yechim o‘tadi. Sariq — chegarada, konstanta va til muhim bo‘lib qoladi. Qizil — bu yechim bilan bormaydi, boshqasini qidiring.
Tez yechim
“Tez yechim” bo'limiga havolaBirinchi yurish ildizdan pastga: otani va chuqurlikni aniqlaymiz va uchlarni ko’rilgan tartibda ro’yxatga yozamiz.
Ikkinchi yurish shu ro’yxat bo’ylab teskari. Bola otadan keyin ko’rilgani uchun, teskari tartibda bola har doim otasidan oldin ishlanadi — demak otaga qo’shish paytida bolaning shoxi tayyor bo’ladi.
n = 6qirralar = [(1, 2), (1, 3), (2, 4), (2, 5), (3, 6)]qoshni = [[] for _ in range(n + 1)]for a, b in qirralar: qoshni[a].append(b) qoshni[b].append(a)ota = [0] * (n + 1)chuqurlik = [0] * (n + 1)tartib = []stek = [1]korilgan = [False] * (n + 1)korilgan[1] = Truewhile stek: u = stek.pop() tartib.append(u) for v in qoshni[u]: if not korilgan[v]: korilgan[v] = True ota[v] = u chuqurlik[v] = chuqurlik[u] + 1 stek.append(v)olcham = [1] * (n + 1)for u in reversed(tartib): if u != 1: olcham[ota[u]] += olcham[u]print(chuqurlik[1:])print(olcham[1:])Avval o'ylang: bu kod nima chiqaradi? Ishga tushirishdan oldin yozing.
n = 6qirralar = [(1, 2), (1, 3), (2, 4), (2, 5), (3, 6)]qoshni = [[] for _ in range(n + 1)]for a, b in qirralar: qoshni[a].append(b) qoshni[b].append(a)ota = [0] * (n + 1)chuqurlik = [0] * (n + 1)tartib = []stek = [1]korilgan = [False] * (n + 1)korilgan[1] = Truewhile stek: u = stek.pop() tartib.append(u) for v in qoshni[u]: if not korilgan[v]: korilgan[v] = True ota[v] = u chuqurlik[v] = chuqurlik[u] + 1 stek.append(v)olcham = [1] * (n + 1)for u in reversed(tartib): if u != 1: olcham[ota[u]] += olcham[u]print(chuqurlik[1:])print(olcham[1:])Haqiqiy natija:
[0, 1, 1, 2, 2, 2] [6, 3, 2, 1, 1, 1]
Javob sekin yechim bilan bir xil. Rekursiya umuman ishlatilmadi — shuning uchun 200 ming uchli zanjirda ham yiqilmaydi.
Javobni ko'rish
[0, 1, 1, 2, 2, 2] [6, 3, 2, 1, 1, 1]
Javob sekin yechim bilan bir xil. Rekursiya umuman ishlatilmadi — shuning uchun 200 ming uchli zanjirda ham yiqilmaydi.
Sinab ko’r
“Sinab ko’r” bo'limiga havolaVizualda avval chuqurliklar ildizdan pastga yoziladi, keyin shox o’lchamlari pastdan yuqoriga yig’iladi.
Daraxt — chuqurlik va shox o'lchami
Avval yozuvlar chuqurlikni, keyin shox o'lchamini ko'rsatadi.
Chuqurlik ildizdan pastga, shox o'lchami esa teskari tartibda — bolalardan otaga qarab yig'iladi.
Algoritmning har qadami quyidagi ro‘yxatda matn sifatida ham berilgan — vizual faqat shu qadamlarni chizadi, yangi ma’lumot qo‘shmaydi.
- Daraxt — sikli yo'q bog'langan graf. Ildiz 1-uch, qolganlarining har birida aniq bitta ota bor.
- 1 uchining chuqurligi 0 — otasidan bitta ko'p.
- 3 uchining chuqurligi 1 — otasidan bitta ko'p.
- 6 uchining chuqurligi 2 — otasidan bitta ko'p.
- 2 uchining chuqurligi 1 — otasidan bitta ko'p.
- 5 uchining chuqurligi 2 — otasidan bitta ko'p.
- 4 uchining chuqurligi 2 — otasidan bitta ko'p.
- Chuqurliklar tayyor. Endi TESKARI yo'nalish: shox o'lchamini bola hisoblanmaguncha otaga qo'shib bo'lmaydi.
- 4 ning shoxida 1 ta uch bor. Bu son otasiga (2) qo'shiladi.
- 5 ning shoxida 1 ta uch bor. Bu son otasiga (2) qo'shiladi.
- 2 ning shoxida 3 ta uch bor. Bu son otasiga (1) qo'shiladi.
- 6 ning shoxida 1 ta uch bor. Bu son otasiga (3) qo'shiladi.
- 3 ning shoxida 2 ta uch bor. Bu son otasiga (1) qo'shiladi.
- Ildizning shoxi — butun daraxt: 6 ta uch.
- Rekursiya umuman ishlatilmadi. Uchlar avval ko'rilgan tartibda yozildi, keyin shu ro'yxat teskari o'qildi — bola har doim otasidan oldin chiqadi.
Daraxt — sikli yo'q bog'langan graf. Ildiz 1-uch, qolganlarining har birida aniq bitta ota bor.
Ishlangan uch0
Xatoni toping
“Xatoni toping” bo'limiga havolaTuzoq — xatoni toping
23 / 40
MasalaHar uch uchun shox o'lchamini toping (o'zi bilan birga).
Taklif qilingan yechim
Bu javobning 3-qismi noto'g'ri. Tartib TESKARI bo'lishi kerak. Ko'rilgan tartibda ota bolalardan oldin turadi, demak otaga qo'shilayotganda bolaning o'lchami hali yig'ilmagan bo'ladi. Natijada har uch faqat bevosita bolalarini sanaydi, nabiralarini emas. To'g'risi: for u in reversed(tartib).
Javobning qaysi qismi noto'g'ri? Bosib belgilang.
Tartib TESKARI bo'lishi kerak. Ko'rilgan tartibda ota bolalardan oldin turadi, demak otaga qo'shilayotganda bolaning o'lchami hali yig'ilmagan bo'ladi. Natijada har uch faqat bevosita bolalarini sanaydi, nabiralarini emas. To'g'risi: for u in reversed(tartib).
Xato hech qanday xabar bermaydi va kichik daraxtda ham noto’g’ri javob beradi — faqat ikki qavatli daraxtda tasodifan to’g’ri chiqadi. Uch qavatli misolda darhol ko’rinadi.
O’zingizni sinang
“O’zingizni sinang” bo'limiga havola1n uchli daraxtda nechta qirra bor?
Javobni ko'rish
Aynan n − 1. Kamroq bo’lsa graf bog’lanmaydi, ko’proq bo’lsa halqa
paydo bo’ladi.
2Nega daraxtda korilgan to'plami shart emas?
Javobni ko'rish
Halqa yo’q, demak uchga faqat otasi orqali kelish mumkin. Qaytib
ketmaslik uchun if v != ota tekshiruvi yetarli.
3Chuqurlik va shox o'lchami qaysi yo'nalishda hisoblanadi?
Javobni ko'rish
Chuqurlik ildizdan pastga (ota ma’lum bo’lgach bola hisoblanadi), shox o’lchami esa pastdan yuqoriga (bolalar ma’lum bo’lgach ota).
4Nega ko'rilgan tartibni teskari o'qish yetarli?
Javobni ko'rish
Bola har doim otasidan keyin ko’riladi, demak teskari tartibda u otasidan oldin ishlanadi. Bu rekursiyaning o’rnini bosadi.
5Daraxtda ikki uch orasida nechta yo'l bor?
Javobni ko'rish
Aynan bitta, u ham eng qisqasi. Shuning uchun daraxtda «eng qisqa yo’l» degan alohida masala yo’q.
Masalalar
“Masalalar” bo'limiga havolaMasalalar
3 ta
- SubordinatesCSES 1674oson
Darsdagi masalaning o‘zi, faqat javobda o‘zini sanamaydi — bittani ayiring.
- Tree DiameterCSES 1131o'rta
Ikki BFS yetadi: istalgan uchdan eng uzoqni toping, keyin o‘shandan eng uzoqni.
- Tree MatchingCSES 1130qiyin
Pastdan yuqoriga yig‘ish sxemasi, lekin har uchda ikki holat: band yoki bo‘sh.
Lokal mashq: mashqlar/23-daraxt/ — masala matni, testlar va tekshir.py. Avval sekin.py ni o‘zingiz yozing, keyin tayyorini oching.
Topshiriq
“Topshiriq” bo'limiga havolaTopshiriq — darajangizni tanlang
Asos · 5–7-sinf — Vizual va aniq ko'rsatmali
Sakkiz kishilik shajara chizing va har kishining chuqurligi bilan shox o’lchamini yozing. Keyin barcha shox o’lchamlarini qo’shing — bu son nimani bildiradi?
Mustahkam · 8–9-sinf — Matnli masala, o'zingiz tuzasiz
23-daraxt masalasini yeching. Yechimingizni zanjir shaklidagi
daraxtda sinang (1-2, 2-3, va hokazo) — bu eng yomon holat.
Chuqur · 10–11-sinf — Algoritmik, chegara holatlari bilan
Sxemani o’zgartirib, har uch uchun uning shoxidagi eng katta chuqurlikni toping (ya’ni shu uchdan pastga eng uzun yo’l). Qaysi bitta qator o’zgardi?
Darsni belgilash uchun JavaScript kerak. Bu progressni saqlash uchun ishlatiladi — darslikning o'zi JavaScript'siz ham to'liq o'qiladi.