30-dars: DSU
4-darajaPlatina — dinamik programmalash25–32 darslar
Bu darsdan keyin siz
- DSU ning ikki amalini yozasiz: topish va birlashtirish
- yo’lni siqish va o’lchamga qarab ulash nima berishini tushuntirasiz
- DSU qaysi masalalarda kerakligini taniysiz
Avval qo’lda
“Avval qo’lda” bo'limiga havolaAvval qo‘lda
Oltita varaqchaga 1 dan 6 gacha raqam yozing va stolga qo’ying. Har varaqchadan o’ziga strelka chizing — hozir har kim o’z guruhining vakili.
Endi «1 va 2 birlashdi» deyilsa, birining strelkasini ikkinchisiga qarating. «Kimning guruhidasan?» degan savolga strelkalar bo’ylab yurib javob bering.
Bir necha birlashtirishdan keyin strelkalar zanjiri uzayib ketadi. Endi qoidani o’zgartiring: javob topilgach, yo’lda uchragan hamma varaqchani to’g’ridan-to’g’ri vakilga qarating.
Nimani sezishingiz kerak
Ikkinchi qoida bilan zanjir uzayib ketmaydi: har so’rov uni kalta qilib qo’yadi. Bu — yo’lni siqish.
Kompyuter yopiq. Bu mashq tugamaguncha kod ochilmaydi.
DSU nima
“DSU nima” bo'limiga havolaDSUdisjoint set union
Bir-biri bilan kesishmaydigan guruhlarni saqlaydigan tuzilma. Ikki amali bor: element qaysi guruhda ekanini topish va ikki guruhni birlashtirish.
Har guruhning bitta vakili bo’ladi va har element vakiliga ko’rsatkich saqlaydi. Vakil o’zini ko’rsatadi.
n = 6ota = list(range(n + 1))def topish(x): while ota[x] != x: x = ota[x] return xota[2] = 1ota[3] = 2print(topish(3), topish(1), topish(5))Avval o'ylang: bu kod nima chiqaradi? Ishga tushirishdan oldin yozing.
n = 6ota = list(range(n + 1))def topish(x): while ota[x] != x: x = ota[x] return xota[2] = 1ota[3] = 2print(topish(3), topish(1), topish(5))Haqiqiy natija:
1 1 5
3 dan 2 ga, 2 dan 1 ga — zanjir bo'ylab yurildi va vakil 1 topildi. 5 esa hali yolg'iz, shuning uchun o'zini ko'rsatadi.
Javobni ko'rish
1 1 5
3 dan 2 ga, 2 dan 1 ga — zanjir bo'ylab yurildi va vakil 1 topildi. 5 esa hali yolg'iz, shuning uchun o'zini ko'rsatadi.
Bu ko’rinish ishlaydi, lekin zanjir uzayib ketishi mumkin: n ta
birlashtirish uzunligi n bo’lgan zanjir hosil qilsa, har so’rov
O(n) turadi.
Sekin yechim
“Sekin yechim” bo'limiga havolaMasala: har birlashtirishdan keyin nechta guruh qolganini chiqaring. Birinchi fikr — har safar grafni boshidan kezib sanash.
n = 6amallar = [(1, 2), (3, 4), (2, 3), (1, 4)]qoshni = [[] for _ in range(n + 1)]javoblar = []for a, b in amallar: qoshni[a].append(b) qoshni[b].append(a) korilgan = [False] * (n + 1) guruhlar = 0 for boshi in range(1, n + 1): if korilgan[boshi]: continue guruhlar += 1 korilgan[boshi] = True stek = [boshi] while stek: u = stek.pop() for v in qoshni[u]: if not korilgan[v]: korilgan[v] = True stek.append(v) javoblar.append(guruhlar)print(javoblar)Avval o'ylang: bu kod nima chiqaradi? Ishga tushirishdan oldin yozing.
n = 6amallar = [(1, 2), (3, 4), (2, 3), (1, 4)]qoshni = [[] for _ in range(n + 1)]javoblar = []for a, b in amallar: qoshni[a].append(b) qoshni[b].append(a) korilgan = [False] * (n + 1) guruhlar = 0 for boshi in range(1, n + 1): if korilgan[boshi]: continue guruhlar += 1 korilgan[boshi] = True stek = [boshi] while stek: u = stek.pop() for v in qoshni[u]: if not korilgan[v]: korilgan[v] = True stek.append(v) javoblar.append(guruhlar)print(javoblar)Haqiqiy natija:
[5, 4, 3, 3]
Oxirgi amalda 1 va 4 allaqachon bitta guruhda edi, shuning uchun son o'zgarmadi. Yechim to'g'ri, lekin har amalda butun graf qaytadan kezildi.
Javobni ko'rish
[5, 4, 3, 3]
Oxirgi amalda 1 va 4 allaqachon bitta guruhda edi, shuning uchun son o'zgarmadi. Yechim to'g'ri, lekin har amalda butun graf qaytadan kezildi.
Nega sekin
“Nega sekin” bo'limiga havolaHar so’rovda butun graf kezib chiqiladi: q × (n + q) amal. Chegara
esa n ≤ 10⁵, q ≤ 2 · 10⁵.
Sig‘adimi?
Bir soniyada taxminan 10⁸ oddiy amal bajariladi.
| Yechim | n = 1 000 | n = 200 000 |
|---|---|---|
Har amalda qayta kezishn^2 | 10⁶sig‘adi | 10¹⁰sig‘maydi |
DSUn | 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 havolaIkkita hiyla zanjirni kalta saqlaydi. Birinchisi — yo’lni siqish: vakil topilgach, yo’lda uchragan hamma element to’g’ridan-to’g’ri vakilga ulanadi. Ikkinchisi — o’lchamga qarab ulash: kichik guruh kattasiga ulanadi, teskarisi emas.
n = 6ota = list(range(n + 1))olcham = [1] * (n + 1)def topish(x): ildiz = x while ota[ildiz] != ildiz: ildiz = ota[ildiz] while ota[x] != ildiz: ota[x], x = ildiz, ota[x] return ildizdef birlashtir(a, b): ra, rb = topish(a), topish(b) if ra == rb: return False if olcham[ra] < olcham[rb]: ra, rb = rb, ra ota[rb] = ra olcham[ra] += olcham[rb] return Trueguruhlar = njavoblar = []for a, b in [(1, 2), (3, 4), (2, 3), (1, 4)]: if birlashtir(a, b): guruhlar -= 1 javoblar.append(guruhlar)print(javoblar)Avval o'ylang: bu kod nima chiqaradi? Ishga tushirishdan oldin yozing.
n = 6ota = list(range(n + 1))olcham = [1] * (n + 1)def topish(x): ildiz = x while ota[ildiz] != ildiz: ildiz = ota[ildiz] while ota[x] != ildiz: ota[x], x = ildiz, ota[x] return ildizdef birlashtir(a, b): ra, rb = topish(a), topish(b) if ra == rb: return False if olcham[ra] < olcham[rb]: ra, rb = rb, ra ota[rb] = ra olcham[ra] += olcham[rb] return Trueguruhlar = njavoblar = []for a, b in [(1, 2), (3, 4), (2, 3), (1, 4)]: if birlashtir(a, b): guruhlar -= 1 javoblar.append(guruhlar)print(javoblar)Haqiqiy natija:
[5, 4, 3, 3]
Javob bir xil. birlashtir allaqachon bir guruhda bo'lganlar uchun False qaytaradi — shuning uchun hisoblagich noto'g'ri kamaymaydi.
Javobni ko'rish
[5, 4, 3, 3]
Javob bir xil. birlashtir allaqachon bir guruhda bo'lganlar uchun False qaytaradi — shuning uchun hisoblagich noto'g'ri kamaymaydi.
Qaysi masalalarda kerak
“Qaysi masalalarda kerak” bo'limiga havolaDSU bitta savolga javob beradi: «bu ikkisi bir guruhdami?» — va guruhlar faqat qo’shiladi, hech qachon bo’linmaydi.
Shu ikki shart bajarilsa DSU ishlaydi: bog’langan guruhlar sonini kuzatish, halqa borligini aniqlash, MST qurish (31-dars). Guruhni ajratish kerak bo’lsa — DSU yaramaydi.
Sinab ko’r
“Sinab ko’r” bo'limiga havolaVizualda uch ustidagi son — uning guruhi vakili. Bir guruhdagilar bir xil sonni ko’rsatishini kuzating.
DSU — birlashtirish va topish
Uch ustidagi son — guruh vakili. Bir guruhdagilar bir xil sonni ko'rsatadi.
Har guruhning vakili bor; birlashtirishda kichik guruh kattasiga ulanadi.
Algoritmning har qadami quyidagi ro‘yxatda matn sifatida ham berilgan — vizual faqat shu qadamlarni chizadi, yangi ma’lumot qo‘shmaydi.
- Boshida har kim o'z guruhida yolg'iz: 6 ta guruh. Uch ustidagi son — uning guruhi vakili.
- 1 va 2 birlashdi. Kichik guruh kattasiga ulandi, yangi vakil — 1. Guruhlar soni: 5.
- 4 va 5 birlashdi. Kichik guruh kattasiga ulandi, yangi vakil — 4. Guruhlar soni: 4.
- 2 va 3 birlashdi. Kichik guruh kattasiga ulandi, yangi vakil — 1. Guruhlar soni: 3.
- 5 va 6 birlashdi. Kichik guruh kattasiga ulandi, yangi vakil — 4. Guruhlar soni: 2.
- 3 va 4 birlashdi. Kichik guruh kattasiga ulandi, yangi vakil — 1. Guruhlar soni: 1.
- 1 va 6 allaqachon bitta guruhda (vakili 1). Hech narsa o'zgarmaydi — bu qirra halqa hosil qilgan bo'lardi.
- Hammasi bitta guruhda. Kichikni kattaga ulash qoidasi zanjirning uzayib ketishiga yo'l qo'ymaydi — shu sababli «vakiling kim?» degan savol deyarli bir qadamda javob oladi.
Boshida har kim o'z guruhida yolg'iz: 6 ta guruh. Uch ustidagi son — uning guruhi vakili.
Amal0
Xatoni toping
“Xatoni toping” bo'limiga havolaTuzoq — xatoni toping
30 / 40
MasalaHar birlashtirishdan keyin guruhlar sonini chiqaring.
Taklif qilingan yechim
Bu javobning 3-qismi noto'g'ri. Ikki xato bir qatorda. Birinchisi: ota[b] = a — VAKIL emas, elementning o'zi ulanmoqda; bu bor bog'lanishlarni buzadi. Ikkinchisi: ular allaqachon bir guruhda bo'lishi tekshirilmayapti, shuning uchun hisoblagich ortiqcha kamayadi. To'g'risi: ota[rb] = ra va faqat ra != rb bo'lganda.
Javobning qaysi qismi noto'g'ri? Bosib belgilang.
Ikki xato bir qatorda. Birinchisi: ota[b] = a — VAKIL emas, elementning o'zi ulanmoqda; bu bor bog'lanishlarni buzadi. Ikkinchisi: ular allaqachon bir guruhda bo'lishi tekshirilmayapti, shuning uchun hisoblagich ortiqcha kamayadi. To'g'risi: ota[rb] = ra va faqat ra != rb bo'lganda.
Ikkinchi xato ayniqsa xavfli: u faqat takroriy birlashtirish bo’lgan testda ko’rinadi. Generator bunday holatni yasamasa, xato stress-testda ham chiqmaydi (15-dars).
O’zingizni sinang
“O’zingizni sinang” bo'limiga havola1DSU ning ikki amali qanday?
Javobni ko'rish
topish(x) — x qaysi guruhda ekanini bilish, birlashtir(a, b) —
ikki guruhni qo’shish.
2Yo'lni siqish nima qiladi?
Javobni ko'rish
Vakil topilgach, yo’lda uchragan hamma elementni to’g’ridan-to’g’ri vakilga ulaydi. Shuning uchun keyingi so’rovlar deyarli bir qadamda javob beradi.
3Nega kichik guruh kattasiga ulanadi?
Javobni ko'rish
Aks holda zanjir uzayib ketadi: har birlashtirishda chuqurlik bittaga oshaveradi. Kichikni kattaga ulash chuqurlikni logarifmik ushlab turadi.
4DSU qanday masalada YARAMAYDI?
Javobni ko'rish
Guruhlarni ajratish kerak bo’lganda. DSU faqat qo’shishni biladi: bir marta birlashgan guruhlarni qaytarib ajratib bo’lmaydi.
5birlashtir nega False qaytaradi?
Javobni ko'rish
Ular allaqachon bitta guruhda bo’lganini bildirish uchun. Shu javobga qarab guruhlar hisoblagichi kamaytiriladi yoki qoldiriladi.
Masalalar
“Masalalar” bo'limiga havolaMasalalar
3 ta
- Road ConstructionCSES 1676o'rta
Darsdagi masalaning o‘zi, ustiga eng katta guruh o‘lchami ham so‘ralgan.
- Road ReparationCSES 1675o'rta
Bu allaqachon MST — 31-darsning masalasi. DSU tayyor bo‘lgach u bir necha qatorga sig‘adi.
- Cut RibbonCodeforces 189Aoson
Bu DSU emas, 1D DP (26-dars) — usulni chalkashtirmaslikni ham mashq qilish kerak.
Lokal mashq: mashqlar/30-guruhlar/ — 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
Oltita varaqcha bilan mashqni takrorlang, lekin bu safar o’lchamga qarab ulashni qo’llang: har safar kichik guruhni kattasiga ulang. Zanjirning eng katta uzunligi qanchaga yetdi?
Mustahkam · 8–9-sinf — Matnli masala, o'zingiz tuzasiz
30-guruhlar masalasini yeching. Takroriy birlashtirish bo’lgan
testni ataylab yasang va yechimingiz to’g’ri javob berishini
tekshiring.
Chuqur · 10–11-sinf — Algoritmik, chegara holatlari bilan
Ikki hiylani alohida o’chirib ko’ring: faqat yo’lni siqish, faqat o’lchamga qarab ulash, ikkalasi ham yo’q. Uch variantni 200 ming amalda o’lchang va vaqtlarni jadvalga yozing.
Darsni belgilash uchun JavaScript kerak. Bu progressni saqlash uchun ishlatiladi — darslikning o'zi JavaScript'siz ham to'liq o'qiladi.