Bölüm 14: Çizgeler
Klasik Soru · Temel Kavramlar
Soru 1: Derece ve El Sıkışma Lemması
V = {0, 1, 2, 3, 4}, E = {(0,1), (0,4), (1,2), (1,3), (1,4), (2,3), (3,4)} yönsüz çizgesinde her düğümün derecesini bulun ve el sıkışma lemmasını (Σ deg(v) = 2m) doğrulayın.
Cevabı göster
| v | 0 | 1 | 2 | 3 | 4 |
|---|---|---|---|---|---|
| deg(v) | 2 | 4 | 2 | 3 | 3 |
Σ deg = 2 + 4 + 2 + 3 + 3 = 14 = 2 · 7 (m = 7). Her kenar iki ucuna birer derece verdiği için toplam her zaman kenar sayısının iki katıdır.
Sonuç: tek dereceli düğüm sayısı (burada 3 ve 4) her zaman çifttir.
Çoktan Seçmeli · Temel Kavramlar
Soru 2: Derece Dizisi Mümkün mü?
Basit yönsüz bir çizgenin düğüm dereceleri 3, 3, 2, 2, 1 olabilir mi?
Doğru C: toplam 11 tek sayı; el sıkışma lemmasına göre toplam 2m olmalı, yani 11 / 2 = 5,5 kenar gerekirdi. A çekici ama böyle bir çizge yoktur; B'deki koşul gerekli ama yeterli değildir.
Çoktan Seçmeli · Temel Kavramlar
Soru 3: Yol Türleri
V = {1, …, 5}, E = {(1,2), (1,3), (1,4), (2,5), (3,4), (4,5)} yönsüz çizgesinde hangisi basit olmayan bir yoldur?
Doğru A: tüm kenarlar (1–4, 4–3, 3–1, 1–2) var ama 1 iki kez geçiyor → yol, fakat basit değil. C çekici ama bir basit döngüdür (yalnızca başlangıç tekrar eder). B basit yoldur; D'de 5–3 kenarı olmadığı için yol değildir.
Çoktan Seçmeli · Temel Kavramlar
Soru 4: Yönlü Kenar ve Komşuluk
Yönlü bir çizgede (u, v) kenarı var, (v, u) kenarı yok. Hangisi kesinlikle doğrudur?
Doğru B: u kuyruk (başlangıç), v baştır (hedef); komşuluk yönlüdür. C çekici ama yanlış: v'den u'ya başka düğümler üzerinden (v → w → u) bir yol olabilir. D: bu kenar u'nun çıkış derecesini artırır.
Klasik Soru · Çizge Gösterimleri
Soru 5: Yönlü Çizgenin Komşuluk Matrisi
Kenarları A→B, A→D, B→C, C→A, D→C, D→E, E→B olan yönlü çizgenin komşuluk matrisini yazın; A'nın çıkış derecesi ve C'nin giriş derecesi matristen nasıl okunur?
Cevabı göster
| A | B | C | D | E | |
|---|---|---|---|---|---|
| A | 0 | 1 | 0 | 1 | 0 |
| B | 0 | 0 | 1 | 0 | 0 |
| C | 1 | 0 | 0 | 0 | 0 |
| D | 0 | 0 | 1 | 0 | 1 |
| E | 0 | 1 | 0 | 0 | 0 |
Satır = kaynak, sütun = hedef. A'nın çıkış derecesi = A satırının toplamı = 2; C'nin giriş derecesi = C sütununun toplamı = 2 (B→C, D→C).
Matris simetrik değildir (ör. A→B var, B→A yok). Bellek O(n²) = 25 hücre, yalnızca 7'si 1.
Çoktan Seçmeli · Çizge Gösterimleri
Soru 6: Ağırlıklı Matriste Boş Hücre
Ağırlıklı bir çizgenin komşuluk matrisinde kenar olmayan hücrelere neden 0 yerine ∞ (ör. Integer.MAX_VALUE) yazılır?
Doğru D: kenarsız hücrede 0, sahte ve bedava bir kenar demektir (köşegendeki 0 ise kendine uzaklık olarak anlamlıdır). B tam tersi: Java int[][]'i zaten 0 ile başlatır; bu yüzden ∞ açıkça doldurulmalıdır.
Klasik Soru · Çizge Gösterimleri
Soru 7: kenarEkle Sonrası Komşuluk Listeleri
Sunumdaki Cizge sınıfıyla (yönsüz kenarEkle) aşağıdaki kod çalıştıktan sonra beş komşu listesinin içeriğini ekleme sırasıyla yazın.
Cizge g = new Cizge(5); int[][] E = {{2,0}, {0,3}, {3,1}, {1,4}, {2,3}, {4,3}}; for (int[] e : E) g.kenarEkle(e[0], e[1]); // kenarEkle(u, v): // komsu.get(u).add(v); // komsu.get(v).add(u);
Cevabı göster
0: [2, 3] · 1: [3, 4] · 2: [0, 3]
3: [0, 1, 2, 4] · 4: [1, 3]
Her kenar iki listeye eklenir → 6 kenar, 12 kayıt (= 2m). Liste uzunluğu dereceyi verir: derece(3) = 4.
Listeler sıralı değildir; sıra ekleme sırasıdır. BFS/DFS'nin ziyaret sırası da bu sıraya bağlıdır. Her kenarEkle O(1), bellek O(n + m).
Çoktan Seçmeli · Çizge Gösterimleri
Soru 8: getEdge Maliyeti
Graph ADT'deki getEdge(u, v) ("u–v kenarı var mı?") işleminin yönsüz çizgede kenar listesi, komşuluk listesi, komşuluk matrisi gösterimlerindeki maliyeti sırasıyla nedir?
Doğru A: kenar listesi tüm kenarları tarar; komşuluk listesinde kısa olan liste taranır; matriste tek hücre m[u][v] okunur. C çekici ama matris sorgusu satırı taramaz; O(n) satır taraması "komşuları gez" işleminin maliyetidir.
Klasik Soru · Çizge Gösterimleri
Soru 9: Gösterim Seçimi: Yol Ağı
n = 10⁵ kavşak ve m = 3 · 10⁵ çift yönlü yoldan oluşan bir yol ağını komşuluk matrisiyle mi, komşuluk listesiyle mi saklarsınız? Bellek gereksinimini sayılarla karşılaştırarak gerekçelendirin.
Cevabı göster
Komşuluk listesi.
- Matris: n² = 10¹⁰ hücre (hücre başına 1 bayt bile ≈ 10 GB); dolu hücre yalnızca 2m = 6 · 10⁵ → %0,006.
- Liste: n liste + 2m = 6 · 10⁵ kayıt → O(n + m) ≈ 7 · 10⁵ öğe, birkaç MB.
Çizge seyrektir (m ≈ 3n). Gezinme de listede O(n + m), matriste O(n²) sürer. Matris; yoğun çizgede (m ≈ n²) ve sık "kenar var mı?" sorgusunda tercih edilir.
Klasik Soru · Gezinme (BFS / DFS)
Soru 10: Hatalı BFS: İşaret Nerede?
Bu BFS'de düğüm kuyruğa eklenirken değil, çıkarılırken işaretleniyor. Kenarları 0–1, 0–2, 1–2 olan üçgende (komşular küçükten büyüğe) bfs(0) ne yazdırır?
void bfs(int s) { boolean[] ziyaret = new boolean[n]; Queue<Integer> q = new ArrayDeque<>(); q.add(s); while (!q.isEmpty()) { int w = q.poll(); ziyaret[w] = true; // işaret burada System.out.print(w + " "); for (int u : komsu.get(w)) if (!ziyaret[u]) q.add(u); } }
Cevabı göster
Çıktı: 0 1 2 2
- 0 çıkar → 1 ve 2 eklenir: q = [1, 2].
- 1 çıkar → 2 henüz işaretsiz, tekrar eklenir: q = [2, 2].
- 2 iki kez çıkar ve iki kez yazdırılır.
Düzeltme: düğüm kuyruğa girerken işaretlenmeli (ziyaret[u] = true; q.add(u);, başta ziyaret[s] = true). Böylece her düğüm kuyruğa bir kez girer; aksi hâlde kuyruk O(m) büyür.
Adım Adım Çalıştırma · Gezinme (BFS / DFS)
Soru 11: BFS Sırası
Komşu listeleri 0: [2, 4] · 1: [3, 5] · 2: [0, 3] · 3: [1, 2, 5] · 4: [0, 5] · 5: [1, 3, 4]. bfs(0) hangi sırayı yazdırır?
0 kuyruğa girerken işaretlenir.
0 kuyruktan çıkar ve yazdırılır; komşuları 2, 4.
2 ve 4 işaretlenip kuyruğa eklenir (seviye 1).
2 çıkar; komşuları 0, 3.
0 zaten işaretli → atlanır; 3 eklenir (seviye 2).
4 çıkar; komşuları 0, 5.
0 atlanır; 5 eklenir (seviye 2).
3 çıkar; komşuları 1, 2, 5.
1 eklenir (seviye 3); 2 ve 5 zaten işaretli.
5 çıkar; komşuları 1, 3, 4 hepsi işaretli → ekleme yok.
1 çıkar; komşuları 3, 5 işaretli.
Kuyruk boş → biter. Seviyeler: {0}, {2, 4}, {3, 5}, {1}. O(n + m).
void bfs(int s) { boolean[] ziyaret = new boolean[n]; Queue<Integer> q = new ArrayDeque<>(); ziyaret[s] = true; q.add(s); while (!q.isEmpty()) { int w = q.poll(); System.out.print(w + " "); for (int u : komsu.get(w)) if (!ziyaret[u]) { ziyaret[u] = true; q.add(u); } } }
Çoktan Seçmeli · Gezinme (BFS / DFS)
Soru 12: Özyinelemeli DFS Sırası
Komşu listeleri alfabetik olan bu çizgede özyinelemeli dfs(H) hangi sırayı yazdırır?
A: B F I B: A C E C: B D E D: C G H E: B C G F: A G G: D E F H: D I: A
Doğru C: H → D → C → B → A (her adımda alfabetik ilk ziyaret edilmemiş komşu) → F → G → E; çıkmazda geri dönülür ve A'dan I'ya gidilir. A çekici ama o BFS sırasıdır (seviye seviye). D'de B'den önce A yerine E seçilmiş.
Klasik Soru · Gezinme (BFS / DFS)
Soru 13: Bağlantılı Bileşenler
n = 8 ve kenarlar (0,4), (4,6), (1,2), (5,7), (7,3) iken bilesenler(bil) çağrısından sonra bil[] dizisi ve dönüş değeri nedir?
int bilesenler(int[] bil) { Arrays.fill(bil, -1); int say = 0; for (int s = 0; s < n; s++) if (bil[s] == -1) dfs(s, say++, bil); return say; } void dfs(int v, int c, int[] bil) { bil[v] = c; for (int u : komsu.get(v)) if (bil[u] == -1) dfs(u, c, bil); }
Cevabı göster
bil = [0, 1, 1, 2, 0, 2, 0, 2], dönüş 3.
- s = 0: dfs {0, 4, 6} → bileşen 0.
- s = 1: dfs {1, 2} → bileşen 1.
- s = 2: zaten boyalı. s = 3: dfs {3, 7, 5} → bileşen 2 (3, 5'ten önce gelir).
Artık "u ile v aynı bileşende mi?" sorusu bil[u] == bil[v] ile O(1). Toplam O(n + m).
Çoktan Seçmeli · Gezinme (BFS / DFS)
Soru 14: İki Parçalı Çizge
Aşağıdaki çizgelerden hangisi iki parçalıdır (BFS ile 2-renklenebilir)?
Doğru C: iki parçalı ⇔ tek uzunlukta döngü yok. C6'da renkler 0, 1, 0, 1, 0, 1 diye gider; kapanış kenarı da zıt renkleri bağlar. B çekici ama C5 tek uzunluklu: BFS aynı renkli iki komşu bulur → false. K4 üçgen içerir.
Adım Adım Çalıştırma · Gezinme (BFS / DFS)
Soru 15: Kahn ile Topolojik Sıralama
adj: 0: [] · 1: [] · 2: [3] · 3: [1] · 4: [0, 1] · 5: [2, 0] olan DAG için kahn(adj) hangi sırayı döndürür?
Giriş dereceleri sayılır: 0 ← 4, 5 · 1 ← 3, 4 · 2 ← 5 · 3 ← 2.
Giriş derecesi 0 olan 4 ve 5 kuyruğa girer: hiçbir şeye bağımlı değiller.
4 çıkar ve sonuca eklenir.
4→0 ve 4→1 silinmiş sayılır; 0 ve 1 hâlâ birer ön koşul bekliyor.
5 çıkar ve sonuca eklenir.
5→2: giris[2] = 0 → 2 kuyruğa; 5→0: giris[0] = 0 → 0 kuyruğa.
2 çıkar ve sonuca eklenir.
2→3: giris[3] = 0 → 3 kuyruğa.
0 çıkar; listesi boş, kimse güncellenmez.
3 çıkar ve sonuca eklenir.
3→1: giris[1] = 0 → 1 kuyruğa.
1 çıkar ve sonuca eklenir.
Kuyruk boş. Boyut 6 = n → döngü yok. Sıra: 4 5 2 0 3 1. O(n + m).
List<Integer> kahn(List<List<Integer>> adj) {
int n = adj.size();
int[] giris = new int[n];
for (List<Integer> l : adj)
for (int v : l) giris[v]++;
Queue<Integer> q = new ArrayDeque<>();
for (int v = 0; v < n; v++)
if (giris[v] == 0) q.add(v);
List<Integer> sonuc = new ArrayList<>();
while (!q.isEmpty()) {
int u = q.poll();
sonuc.add(u);
for (int v : adj.get(u))
if (--giris[v] == 0) q.add(v);
}
return sonuc; // boyut < n → döngü
}Klasik Soru · Gezinme (BFS / DFS)
Soru 16: Hatalı Döngü Tespiti
renk[v] = 2 satırı unutulmuştur. Kenarları 0→1, 0→2, 1→2 olan DAG için donguVar(0, renk) ne döndürür ve neden?
// renk: 0 beyaz, 1 gri, 2 siyah boolean donguVar(int v, int[] renk) { renk[v] = 1; for (int u : komsu.get(v)) { if (renk[u] == 1) return true; if (renk[u] == 0 && donguVar(u, renk)) return true; } // renk[v] = 2; (unutulmuş) return false; }
Cevabı göster
true döner: döngü olmadığı hâlde yanlış alarm.
- 0 gri → 1 gri → 2 gri; 2'nin çıkan kenarı yok, false döner ama 2 gri kalır. 1 de gri kalır.
- 0'a dönülür; 0→2 kenarında renk[2] == 1 → geri kenar sanılır.
Doğrusu: işi biten düğüm siyah (2) olmalı. Yalnızca gri (şu anki yolda) düğüme giden kenar döngü demektir; siyaha giden kenar döngü değildir. Düzeltilmiş kod false döndürür.
Çoktan Seçmeli · En Kısa Yol
Soru 17: Ağırlıklı Çizgede BFS
Bu ağırlıklı yönlü çizgede BFS'nin A'dan F'ye bulduğu yolun ağırlıklı uzunluğu nedir (komşular alfabetik)?
A→B 4 A→C 2 B→C 5 B→D 10 C→E 3 E→D 4 D→F 11
Doğru B: BFS en az kenarlı yolu bulur: A→B→D→F (3 kenar) = 4 + 10 + 11 = 25. A çekici ama 20, gerçek en kısa yol A→C→E→D→F'nin uzunluğudur (Dijkstra'nın sonucu). C kenar sayısıdır, ağırlık değil.
Klasik Soru · En Kısa Yol
Soru 18: Dijkstra'yı Elle Uygulama
Ağırlıklı yönsüz çizgede A'dan başlayarak Dijkstra ile her düğümün en kısa mesafesini ve onceki[] değerini bulun; düğümler hangi sırayla kesinleşir?
Cevabı göster
| A | B | C | D | E | F | G | |
|---|---|---|---|---|---|---|---|
| d | 0 | 3 | 2 | 8 | 10 | 13 | 14 |
| önceki | – | C | A | B | D | E | F |
Kesinleşme sırası: A C B D E F G
- C = 2 kesinleşince B, 4'ten 2 + 1 = 3'e iner.
- D = 3 + 5 = 8 (A–C–D = 10'dan iyi); E = 8 + 2 = 10 (C–E ile 12).
- F = 10 + 3 = 13 (D–F ile 14); G = 13 + 1 = 14 (E–G ile 17).
Çoktan Seçmeli · En Kısa Yol
Soru 19: Bayat Kayıt Kontrolü
Java Dijkstra'da işaretli continue satırı silinirse (ağırlıklar ≥ 0) ne olur?
long[] e = pq.poll(); int u = (int) e[0]; if (e[1] > d[u]) continue; // bayat for (int[] k : adj.get(u)) { int v = k[0]; long alt = d[u] + k[1]; if (alt < d[v]) { d[v] = alt; pq.add(new long[]{v, alt}); } }
Doğru D: bayat kayıt çıktığında d[u] zaten daha küçüktür ve komşular bu d[u] ile önceden gevşetilmiştir; alt < d[v] bir daha sağlanmaz. A çekici ama satır doğruluk için değil verim içindir (Java PQ'da "önceliği azalt" olmadığından eklenen kopyalar).
Klasik Soru · Minimum Kapsayan Ağaç
Soru 20: Kruskal ile MKA
Çizgenin minimum kapsayan ağacını (MKA) Kruskal algoritmasıyla bulunuz: kenarları seçilme sırasıyla ve toplam ağırlığı yazınız; algoritma hangi kenardan sonra durur?
Cevabı göster
| Kenar | w | find(u) ≠ find(v)? | Karar |
|---|---|---|---|
| E–F | 1 | evet | kabul |
| B–D | 2 | evet | kabul |
| A–C | 3 | evet | kabul |
| C–E | 4 | evet | kabul |
| B–C | 5 | evet | kabul → |T| = 5 = n − 1 |
Toplam ağırlık 1 + 2 + 3 + 4 + 5 = 15. B–C'den sonra |T| = n − 1 olduğu için algoritma durur; A–B (6), C–D (7), D–E (8), D–F (9) hiç incelenmez. İncelenseydi A–B reddedilirdi: A ile B zaten A–C–B yoluyla aynı kümede (döngü).
Union-Find, "bu kenar döngü kurar mı?" sorusunu find(u) == find(v) karşılaştırmasıyla neredeyse sabit sürede yanıtlar.
Çoktan Seçmeli · Minimum Kapsayan Ağaç
Soru 21: Kruskal'ın Maliyeti
n düğümlü, m kenarlı bir çizgede Union-Find ile uygulanan Kruskal algoritmasının toplam süresini hangi aşama belirler?
Doğru: D. 2m find + (n − 1) union yalnızca O(m · α(n)), yani neredeyse doğrusal; baskın terim sıralamadır. m ≤ n² olduğundan log m ≤ 2 log n, dolayısıyla O(m log m) = O(m log n). B çekicidir, ama döngü kontrolü Union-Find yerine DFS ile yapılsaydı geçerli olurdu.
Klasik Soru · Minimum Kapsayan Ağaç
Soru 22: Prim ile MKA
Soru 20'deki çizgede Prim algoritmasını A'dan başlatınız. Ağaca giren kenarları sırasıyla ve toplam ağırlığı yazınız. Sonuç Kruskal'ınkiyle karşılaştırıldığında ne görülür?
Cevabı göster
| Adım | Ağaç | En hafif dış kenar |
|---|---|---|
| 1 | A | A–C 3 |
| 2 | A, C | C–E 4 |
| 3 | A, C, E | E–F 1 |
| 4 | A, C, E, F | C–B 5 |
| 5 | A, B, C, E, F | B–D 2 |
Toplam 3 + 4 + 1 + 5 + 2 = 15: Kruskal'la aynı kenarlar, farklı sırada. Prim E–F (1) kenarını ancak E ağaca girince görebilir; Kruskal onu ilk seçer.
Çoktan Seçmeli · Minimum Kapsayan Ağaç
Soru 23: Prim'in Seçimi
Prim algoritması her adımda hangi kenarı ağaca ekler?
Doğru: C. Kenarın bir ucu ağaçta, öbür ucu dışarıda olmalıdır; bu kenarların en hafifi seçilir. A Kruskal'ın kuralıdır (döngü kontrolüyle). B Dijkstra'nın anahtarıdır. D yanlıştır: en hafif dış kenar daha önce eklenmiş bir düğümden çıkabilir.
Çoktan Seçmeli · Minimum Kapsayan Ağaç
Soru 24: Bayat Kayıt
Öncelikli kuyrukla yazılan tembel Prim'de if (agacta[e[1]]) continue; satırı silinirse ne olur?
Doğru: B. v ağaca girdikten sonra v'ye giden eski kayıtlar kuyrukta kalır. Bu kontrol olmadan böyle bir kayıt çıktığında iki ucu da ağaçta olan bir kenar T'ye eklenir: döngü oluşur ve kapsayan ağaç bozulur.