Bölüm 17: Minimum Kapsayan Ağaçlar
Çoktan Seçmeli · Kapsayan Ağaçlar
Soru 1: Ağaç Dışı Kenar Eklemek
Bağlantılı bir çizgenin bir kapsayan ağacına ağaç dışı kenarlardan biri ekleniyor. Hangisi doğrudur?
B: Ağaçta her düğüm çifti arasında tek yol vardır; eklenen (u, v) kenarı bu yolla birlikte tek bir döngü kurar. Döngüden herhangi bir kenarı silmek bağlantıyı koparmaz ve n − 1 kenar kalır: yeni bir kapsayan ağaç. Kapsayan ağaçları üretme yöntemi buna dayanır.
Çoktan Seçmeli · Kapsayan Ağaçlar
Soru 2: Her Zaman Doğru Olmayan
n düğümlü bağlantılı bir çizgenin kapsayan ağacı için hangisi her zaman doğru değildir?
D: Yıldız biçimli bir kapsayan ağaçta merkezin derecesi n − 1'dir (K4'ün dört yıldız biçimli kapsayan ağacı gibi). D yalnız yol biçimli ağaçlarda doğrudur. A, B ve C ağacın tanımından gelir: bağlantılı, döngüsüz ve en az kenarlı.
Klasik Soru · Kapsayan Ağaçlar
Soru 3: DFS ve BFS Ağaçları
Komşuluk listeleri küçükten büyüğe sıralı. 0'dan başlayan özyinelemeli DFS ve BFS hangi ağaç kenarlarını seçer? Her birinde kaç kenar ağaç dışında kalır?
Cevabı göster
DFS(0): (0,1), (1,2), (2,3), (3,4), (4,5): her adımda ilk ziyaret edilmemiş komşuya inilir; ağaç bir yoldur.
BFS(0): (0,1), (0,2), (1,3), (1,5), (2,4): önce 0'ın, sonra 1'in ve 2'nin komşuları.
solda DFS, sağda BFS ağacı (kalın)
İkisinde de 10 − (6 − 1) = 5 kenar ağaç dışıdır. DFS'de N = {(0,2), (1,3), (1,5), (2,4), (3,5)}, BFS'de N = {(1,2), (2,3), (3,4), (3,5), (4,5)}. Sayı aynı, kenarlar farklı.
Çoktan Seçmeli · Minimum Maliyet
Soru 4: En Ucuz Kenar
Kenar ağırlıkları birbirinden farklı, bağlantılı bir çizgede en ucuz kenar için hangisi kesinlikle doğrudur?
A: Kesit özelliği: kenarın bir ucunu bir yana, diğerini öbür yana koyan bir kesitte bu kenar kesiti geçen en ucuz kenardır; bu yüzden bir MST'de bulunur, ağırlıklar farklı olduğundan MST tektir. Kruskal onu ilk adımda seçer. Prim nereden başlarsa başlasın uçlardan biri ağaca girdiğinde bu kenar adayların en ucuzudur.
Adım Adım Çalıştırma · Kruskal
Soru 5: Kruskal ve ata Dizisi
Şekildeki çizgede Kruskal çalıştırılıyor (birlestir ağırlıklı, kume_bul azaltmasız). Hangi kenarlar seçilir, hangisi reddedilir, sonda ata nedir?
Kenarlar sıralandı: 2, 3, 4, 5, 6, 7, 8, 9, 10, 11. Her düğüm ayrı küme.
(3,4) = 2: kökler 3 ve 4 farklı → ağaca. Toplam 2.
(0,2) = 3: kökler 0 ve 2 farklı → ağaca. Toplam 5.
(0,1) = 4: kökler 0 ve 1 farklı → ağaca. Toplam 9.
(1,2) = 5: iki ucun kökü de 0 → döngü, bırakılır.
(3,5) = 6: kökler 3 ve 5 farklı → ağaca. Toplam 15.
(2,3) = 7: kökler 0 ve 3 farklı → ağaca. Toplam 22.
t = n − 1 = 5: döngü biter. (2,4), (1,3), (4,5), (1,5) kenarlarına hiç bakılmadı. MST maliyeti 22.
for (i = 0; i < n; i++) ata[i] = -1; qsort(k, e, sizeof(kenar), kars); for (i = 0, t = 0; i < e && t < n - 1; i++) { int a = kume_bul(ata, k[i].u); int b = kume_bul(ata, k[i].v); if (a != b) { /* döngü yok */ T[t++] = k[i]; birlestir(ata, a, b); } /* yoksa bırak */ } if (t < n - 1) printf("agac yok\n");
Çoktan Seçmeli · Kruskal
Soru 6: Yanlış Döngü Denetimi
Kruskal'da döngü denetimi union-find yerine "kenarın iki ucu da daha önce seçilmiş mi?" sorusuyla yapılıyor. Şekildeki çizgede ne olur?
C: (3,4), (0,2), (0,1) alınır; (1,2)'nin iki ucu seçili olduğundan reddedilir (burada karar doğru). (3,5) alınır. (2,3)'ün iki ucu da seçilmiştir ama farklı öbeklerdedir ({0,1,2} ve {3,4,5}); kenar reddedilir. Sonraki kenarların uçları da hep seçili olduğundan 4 kenarda kalınır. Uçların seçilmiş olması aynı öbekte oldukları anlamına gelmez.
Çıktı Sorusu · Kruskal
Soru 7: Ters Karşılaştırma
Şekildeki çizgede Kruskal döngüsü değiştirilmeden yalnız qsort'a aşağıdaki kars_ters veriliyor. Program ne yazdırır? Bulunan ağaç nedir?
int kars_ters(const void *x, const void *y) { const kenar *a = x, *b = y; return b->w - a->w; } /* ... */ qsort(k, e, sizeof(kenar), kars_ters); /* Kruskal döngüsü aynı; toplam += k[i].w */ for (j = 0; j < t; j++) printf("(%d,%d) ", T[j].u, T[j].v); printf("= %d\n", toplam);
Cevabı göster
Çıktı: (1,5) (4,5) (2,4) (1,3) (0,1) = 42
- Kenarlar büyükten küçüğe denenir: 11, 10, 9, 8 alınır. (2,3) 7, (3,5) 6, (1,2) 5 döngü kurar ve bırakılır; (0,1) 4 alınır, t = 5.
- Açgözlü seçim yine doğru çalışır ama amaç tersine dönmüştür: bu, en büyük kapsayan ağaçtır (42). Minimum ağaç 22'dir.
Karşılaştırıcının yönü algoritmanın neyi en iyilediğini belirler.
Çoktan Seçmeli · Kruskal
Soru 8: Kruskal'ın Mertebesi
n = 1000 düğüm, e = 3000 kenarlı seyrek bir çizgede Kruskal qsort ve ağırlıklı union-find ile çalıştırılıyor. Toplam zamanın mertebesi nedir?
B: Sıralama O(e log e). Kenar başına iki kume_bul ağırlıklı birleşimle O(log n), toplam O(e log n); e ≤ n² olduğundan log e ≤ 2 log n ve ikisi aynı mertebededir. C listelerde arayan "kötü" kodlamanın, A dizili Prim'in maliyetidir. D için azaltma kuralı da gerekir ve sıralama yine kalır.
Hata Bulma · Kruskal
Soru 9: Kök Yerine Uç
Kruskal döngüsünde tek satır değişmiştir. Şekildeki çizgede program yine 22 bulur. Hata nedir, sonda ata neden yanlıştır, hata hangi durumda sonucu bozar?
for (i = 0, t = 0; i < e && t < n - 1; i++) { int a = kume_bul(ata, k[i].u); int b = kume_bul(ata, k[i].v); if (a != b) { T[t++] = k[i]; birlestir(ata, k[i].u, k[i].v); } }
Cevabı göster
birlestir'e kökler (a, b) yerine kenarın uçları veriliyor. (2,3) işlenirken a = 0, b = 3 bulunur ama birlestir(ata, 2, 3) çağrılır: ata[2] = 0 ≤ −3 yanlış, 2 kendi kökünden koparılıp 3'ün altına bağlanır.
Sonda ata = [−3, 0, 3, −3, 3, 3]: iki kök kalmıştır ({0,1} ve {2,3,4,5}) ve 0'ın sayacı yanlıştır. Kod 22 bulur, çünkü t = 5 olunca döngü biter. Bir kenar daha işlenseydi (1,3) farklı kökler (0 ve 3) verir ve döngü kurduğu hâlde alınırdı (simülasyonla doğrulandı).
Düzeltme: birlestir(ata, a, b);. Doğru bir sonuç, kodun doğru olduğunu göstermez.
Çoktan Seçmeli · Prim
Soru 10: Prim'de Sıra
Şekildeki çizgede Prim 5 numaralı düğümden başlatılıyor. Düğümler ağaca hangi sırayla katılır?
A: 5'in adayları (5,3) 6, (5,4) 10, (5,1) 11 → 3. Sonra (3,4) 2 → 4. Adaylar (3,2) 7, (3,1) 8, (4,2) 9, (5,1) 11 → 2. Ardından (2,0) 3 → 0 ve (0,1) 4 → 1. Toplam yine 22'dir: başka başlangıç aynı ağacı başka sırayla kurar. B'de 0'a henüz bağlı bir kenar yoktur.
Adım Adım Çalıştırma · Prim
Soru 11: Dizili Prim
O(n²) Prim 0'dan başlatılıyor. Her turda hangi düğüm seçilir, enaz nasıl değişir? (Düğümlerin yanında enaz değerleri, ✓: ağaçta.)
TV = {0}. enaz[v] = 0'a doğrudan kenarın maliyeti: 1 → 4, 2 → 3; diğerleri ∞.
En küçük enaz: u = 2, kenar (0,2) = 3 ağaca; güncellenen: enaz[3] = 7, enaz[4] = 9.
En küçük enaz: u = 1, kenar (0,1) = 4 ağaca; güncellenen: enaz[5] = 11.
En küçük enaz: u = 3, kenar (2,3) = 7 ağaca; güncellenen: enaz[4] = 2, enaz[5] = 6.
En küçük enaz: u = 4, kenar (3,4) = 2 ağaca; güncelleme yok.
En küçük enaz: u = 5, kenar (3,5) = 6 ağaca; güncelleme yok. Toplam 22: Kruskal ile aynı ağaç.
secildi[0] = 1; /* TV = {0} */ for (v = 0; v < n; v++) enaz[v] = w[0][v], yakin[v] = 0; for (k = 1; k < n; k++) { u = en_yakin(enaz, secildi, n); /* O(n) */ if (u < 0) break; /* agac yok */ secildi[u] = 1; toplam += enaz[u]; for (v = 0; v < n; v++) if (!secildi[v] && w[u][v] < enaz[v]) enaz[v] = w[u][v], yakin[v] = u; }
Adım Adım Çalıştırma · Prim
Soru 12: Sollin Turları
Sollin (Borůvka) algoritması şekildeki çizgede çalıştırılıyor. Her turda hangi kenarlar seçilir, kaç tur gerekir?
Her düğüm ayrı bir bileşen.
Tur 1 seçimleri: 0 → (0,2) 3, 1 → (0,1) 4, 2 → (0,2) 3, 3 → (3,4) 2, 4 → (3,4) 2, 5 → (3,5) 6. Aynı kenarı iki bileşen seçebilir.
Dört farklı kenar eklenir; (0,2) ve (3,4) ikinci kez geldiğinde uçlar artık aynı kümededir. Bileşenler {0,1,2} ve {3,4,5}.
Tur 2: iki bileşen de kendisinden çıkan en ucuz kenar olarak (2,3) 7'yi seçer.
(2,3) eklenir, tek bileşen kaldı. İki turda toplam 22: Kruskal ve Prim ile aynı ağaç. Her turda bileşen sayısı en az yarıya iner.
for (i = 0; i < n; i++) ata[i] = -1; while (bilesen > 1) { for (her bileşen C) en[C] = C'den çıkan en ucuz kenar; for (her bileşen C) if (en[C]'nin uçları farklı kümede) { T'ye ekle; birlestir(...); bilesen--; } }
Klasik Soru · Prim
Soru 13: MST ile En Kısa Yol
Şekildeki çizgenin MST'sinde (toplam 22) 0'dan 5'e giden yolun uzunluğu nedir? Çizgede 0'dan 5'e en kısa yol kaçtır? 0 kökünden en kısa yol ağacının toplam kenar maliyeti nedir?
Cevabı göster
- MST'de 0'dan 5'e tek yol 0 – 2 – 3 – 5: 3 + 7 + 6 = 16.
- En kısa yol 0 – 1 – 5: 4 + 11 = 15. MST, tek tek uzaklıkları en aza indirmez.
- En kısa yol ağacı (Dijkstra, kaynak 0): (0,1) 4, (0,2) 3, (2,3) 7, (2,4) 9, (1,5) 11. Uzaklıklar 4, 3, 10, 12, 15. Toplam kenar maliyeti 34 > 22.
MST toplam bağlantı maliyetini, en kısa yol ağacı kökten her düğüme uzaklığı en aza indirir; amaçlar farklıdır.
Çoktan Seçmeli · Prim
Soru 14: Bağlantısız Çizge
İki bileşenli bir çizgede ({0, 1, 2} ve {3, 4}) dizili Prim 0'dan, Kruskal da bütün kenarlarla çalıştırılıyor. Hangisi doğrudur?
D: Prim'de işaretsiz düğümlerin hepsi ∞ olunca en_yakin −1 döner ve döngü kırılır: yalnız 0'ın bileşeni kapsanır. Kruskal kenarları bileşenlerin içinde birleştirir; 2 + 1 = 3 kenar seçer, t < n − 1 olduğu için "agac yok" yazar ama seçtikleri bir minimum kapsayan ormandır.
Çoktan Seçmeli · Özet
Soru 15: Kruskal mı Prim mi?
Kruskal ve Prim için hangisi yanlıştır?
C: Prim yalnız bir ucu ağaçta (TV), diğer ucu dışarıda olan kenarları aday sayar; v ∉ TV koşulu döngüyü zaten engeller. Union-find Kruskal'ın ihtiyacıdır, çünkü onun öbekleri ayrık büyür (A). B: her turda n düğüm taranır. D: farklı ağırlıklarda MST tektir.
Kod Yazma · Özet
Soru 16: Kapsayan Ağaç mı?
n düğümlü bir çizge için t kenarlık T dizisinin bir kapsayan ağaç olup olmadığını union-find ile sınayan int kapsayan_mi(int n, const kenar T[], int t) yordamını yazın (1: evet, 0: hayır, −1: bellek yok). ata dizisi heap'te ayrılsın.
Cevabı göster
int kapsayan_mi(int n, const kenar T[], int t) { int *ata = malloc(n * sizeof *ata); if (ata == NULL) return -1; for (int i = 0; i < n; i++) ata[i] = -1; int sonuc = (t == n - 1); /* kenar sayısı */ for (int i = 0; sonuc && i < t; i++) { int a = kume_bul(ata, T[i].u); int b = kume_bul(ata, T[i].v); if (a == b) sonuc = 0; /* döngü */ else birlestir(ata, a, b); } free(ata); return sonuc; }
n − 1 kenar ve döngü yok ise ağaç bağlantılıdır. Örnek çizgede Kruskal'ın ağacı 1, (1,2) eklenip (2,3) çıkarılmış küme 0 (0–1–2 döngüsü), dört kenar 0 verir. Her çıkışta free çalışır.