L17 · Δυναμικός Προγραμματισμός IV — Ανεξάρτητο Σύνολο σε Δέντρα & Bellman-Ford
Τι θα δούμε
Φτάσαμε στην τελευταία διάλεξη. Σε όλον τον δυναμικό προγραμματισμό μέχρι τώρα (L14–L16) το υποπρόβλημα είχε σχεδόν πάντα το ίδιο σχήμα: «τα πρώτα στοιχεία μιας ακολουθίας». Σήμερα το υποπρόβλημα γίνεται κάτι πιο πλούσιο — ένα κομμάτι ενός γραφήματος:
- Ανεξάρτητο σύνολο σε δέντρα — DP όπου τα υποπροβλήματα είναι υποδέντρα.
- Bellman-Ford — συντομότερες διαδρομές όταν κάποιες ακμές έχουν αρνητικό βάρος, εκεί ακριβώς που ο Dijkstra του L09 τα παρατάει. Έτσι κλείνει και μια υπόσχεση που έμεινε ανοιχτή από τότε.
Ανεξάρτητο σύνολο σε δέντρα — «το πάρτι»
Το πρόβλημα
Οργανώνουμε ένα πάρτι για μια εταιρεία με αυστηρή ιεραρχική δομή. Κάθε υπάλληλος έχει μια θετική «προσφορά» — πόσο κέφι φέρνει στο πάρτι. Ένας περιορισμός: δεν καλούμε ταυτόχρονα έναν υπάλληλο και τον άμεσο προϊστάμενό του.
Είσοδος: ένα δέντρο που περιγράφει την ιεραρχία, με μια προσφορά σε κάθε κορυφή.
Στόχος: μια λίστα καλεσμένων με το μέγιστο άθροισμα προσφορών, που σέβεται τον περιορισμό.
Δύο τιμές ανά κορυφή
Όπως σε κάθε DP (L14), το πρώτο βήμα είναι να βρούμε το σωστό υποπρόβλημα. Εδώ η επιλογή είναι φυσική: για κάθε κορυφή , κοίτα μόνο το υποδέντρο της — την και όλους τους απογόνους της. Αν λύσουμε κάθε υποδέντρο, η απάντηση για ολόκληρο το δέντρο είναι απλώς το υποδέντρο της ρίζας.
Μένει να συνδέσουμε ένα υποδέντρο με τα υποδέντρα των παιδιών του. Κι εδώ κρύβεται μια παγίδα.
Μία τιμή ανά κορυφή δεν αρκεί. Ας υποθέσουμε ότι για κάθε κορυφή κρατάμε έναν μόνο αριθμό: «το βάρος του καλύτερου ανεξάρτητου συνόλου μέσα στο υποδέντρό της». Ακούγεται λογικό — αλλά σπάει. Όταν αποφασίζουμε για μια κορυφή , αν την βάλουμε μέσα τότε κανένα παιδί της δεν επιτρέπεται. Χρειαζόμαστε λοιπόν να ξέρουμε «το καλύτερο του υποδέντρου ενός παιδιού χωρίς το ίδιο το παιδί». Ένας μόνο αποθηκευμένος αριθμός δεν το ξεχωρίζει αυτό — μπορεί κρυφά να περιλαμβάνει το παιδί, κι έτσι η σύνθεση βγάζει παράνομο σύνολο. Δοκίμασέ το:
Ανεξάρτητο σύνολο = κανένα ζευγάρι γειτόνων μαζί. Ο αριθμός σε κάθε κορυφή είναι η προσφορά χ.
Το p μένει έξω. Δεν μπλοκάρει κανέναν — η καλύτερη απάντηση για το υποδέντρο του p είναι απλώς το καλύτερο σύνολο του υποδέντρου του c: 9, που το πετυχαίνει το σύνολο {c}.
Η λύση είναι ακριβώς αυτό που έδειξε το παράδειγμα: κρατάμε δύο τιμές ανά κορυφή, μία για κάθε σενάριο.
Έστω με παιδιά (άμεσους υφισταμένους) .
Για το : η δεν μπαίνει — άρα δεν μπλοκάρει κανέναν. Κάθε υφιστάμενος επιλέγει ελεύθερα· για κάθε υποδέντρο παίρνουμε το βέλτιστο :
Για το : δύο σενάρια, παίρνουμε το καλύτερο.
- Η δεν μπαίνει: αυτό είναι ακριβώς το .
- Η μπαίνει: τότε κανένα από τα παιδιά δεν επιτρέπεται, οπότε κάθε υποδέντρο συνεισφέρει το . Συνολικά: .
Ο αλγόριθμος
- Είσοδος:
- δέντρο με προσφορά χ(v) σε κάθε κορυφή
- Έξοδος:
- η μέγιστη συνολική προσφορά ενός ανεξάρτητου συνόλου
Με λόγια. Υπολογίζουμε τα από τα φύλλα προς τη ρίζα — κάθε κορυφή χρειάζεται πρώτα τα παιδιά της. Για φύλλο : και . Για εσωτερική κορυφή, εφαρμόζουμε τους δύο τύπους. Η τελική απάντηση είναι το .
Πολυπλοκότητα. Κάθε κορυφή και κάθε ακμή επεξεργάζεται φορές → συνολικά.
Δες τον υπολογισμό να ανεβαίνει από τα φύλλα στη ρίζα. Σε κάθε κορυφή εμφανίζονται τα και της — και στο τέλος φωτίζεται η βέλτιστη λίστα καλεσμένων:
A[v] = καλύτερο στο υποδέντρο · B[v] = καλύτερο χωρίς την v.
Συντομότερες διαδρομές με αρνητικά βάρη
Γιατί ξαναπιάνουμε το πρόβλημα
Στο L09 λύσαμε το πρόβλημα της συντομότερης διαδρομής με τον αλγόριθμο Dijkstra — αλλά με μια ρητή προϋπόθεση: όλα τα βάρη των ακμών έπρεπε να είναι θετικά. Τώρα ρίχνουμε αυτόν τον περιορισμό και επιτρέπουμε και αρνητικά βάρη . Φαντάσου ένα δίκτυο όπου κάποιες ακμές κοστίζουν, ενώ άλλες αποδίδουν «κέρδος» — μια πληρωμή, μια έκπτωση, ενέργεια που ανακτάς.
Ακούγεται μικρή αλλαγή. Δεν είναι: όπως θα δούμε αμέσως, ο Dijkstra μπορεί τώρα να δώσει λάθος απάντηση — και το ίδιο και κάθε εύκολο μπάλωμα που θα σου ερχόταν στο μυαλό.
Γιατί ο Dijkstra αποτυγχάνει
Θυμήσου την καρδιά του Dijkstra (L09): σε κάθε βήμα οριστικοποιεί την κορυφή με τη μικρότερη προσωρινή απόσταση και δεν την ξανακοιτάζει ποτέ. Αυτό στηρίζεται σε μια σιωπηρή υπόθεση: «αν μια κορυφή έχει αυτή τη στιγμή τη μικρότερη απόσταση, τίποτα στο μέλλον δεν μπορεί να τη βελτιώσει». Με θετικά βάρη η υπόθεση ισχύει — κάθε επιπλέον ακμή μόνο προσθέτει κόστος.
Με μια αρνητική ακμή, η υπόθεση καταρρέει: μια ακμή μπορεί να αφαιρέσει κόστος, οπότε ένα μονοπάτι με περισσότερες ακμές μπορεί τελικά να βγει φθηνότερο. Όμως ο Dijkstra έχει ήδη κλειδώσει την κορυφή. Δες το να συμβαίνει, στο μικρότερο δυνατό παράδειγμα:
Πράσινο = οριστικοποιημένη (κλειδωμένη) · κόκκινο = εξάγεται τώρα.
Γιατί δεν αρκεί να προσθέσεις μια σταθερά
Εντάξει — ο Dijkstra θέλει θετικά βάρη. Να μια ιδέα που μοιάζει να σώζει την κατάσταση: βρες το πιο αρνητικό βάρος και πρόσθεσε μια αρκετά μεγάλη σταθερά σε όλες τις ακμές, ώστε να γίνουν όλες θετικές. Μετά τρέξε ήσυχα τον Dijkstra.
Δεν δουλεύει — και αξίζει να καταλάβεις γιατί, γιατί το λάθος είναι λεπτό. Όταν προσθέτεις σε κάθε ακμή, μια διαδρομή με πολλές ακμές μαζεύει το πολλές φορές, ενώ μια διαδρομή με λίγες ακμές το μαζεύει λίγες. Οι δύο διαδρομές δεν επιβαρύνονται το ίδιο — άρα η σύγκρισή τους αλλοιώνεται, και η συντομότερη μπορεί να αλλάξει. Σύρε το και δες τη σωστή απάντηση να ανατρέπεται:
Δύο διαδρομές. Πραγματικά μήκη: A = 2, B = −1 — άρα η Διαδρομή B — 4 ακμές είναι όντως η συντομότερη.
Αρνητικοί κύκλοι
Πριν φτιάξουμε τον αλγόριθμο, πρέπει να ξεκαθαρίσουμε ένα όριο. Με αρνητικά βάρη, μερικές φορές δεν υπάρχει καν συντομότερη διαδρομή.
Φαντάσου έναν κύκλο του οποίου τα βάρη αθροίζουν σε αρνητικό αριθμό. Κάθε φορά που τον διασχίζεις ολόκληρο, το συνολικό σου κόστος πέφτει κατά ένα σταθερό ποσό. Αν στον δρόμο σου προς τον προορισμό μπορείς να φτάσεις σε έναν τέτοιο κύκλο, μπορείς να γυρνάς μέσα του ξανά και ξανά, ρίχνοντας το κόστος όσο χαμηλά θέλεις. Δεν υπάρχει «καλύτερη» διαδρομή — υπάρχει πάντα μια ακόμη φθηνότερη:
Η διαδρομή s→t περνά από τον κύκλο a→b→c→a, που έχει άθροισμα βαρών −3.
Ο κύκλος a→b→c→a: 2 + 1 + (−6) = −3 ανά γύρο.
Κράτα αυτό το «απλή»: θα μας φανεί χρήσιμο σε λίγο. Μια απλή διαδρομή σε γράφημα με κορυφές έχει το πολύ ακμές — δεν γίνεται να έχει περισσότερες χωρίς να ξαναπεράσει από κάποια κορυφή.
Ο αλγόριθμος Bellman-Ford
Η αναδρομή — παραμετροποίηση με το πλήθος ακμών
Ξέρουμε ήδη τη συνταγή του DP (L14): σπάσε το πρόβλημα σε υποπροβλήματα, βάλ' τα σε μια σειρά ώστε καθένα να εξαρτάται μόνο από προηγούμενα, και λύσε τα με αυτή τη σειρά.
Εδώ σκοντάφτουμε. Σε ένα γράφημα με κύκλους, η «συντομότερη διαδρομή ως την » μπορεί να εξαρτάται από τη «συντομότερη διαδρομή ως την », που με τη σειρά της εξαρτάται πάλι από την . Τα υποπροβλήματα είναι μπλεγμένα κυκλικά — δεν υπάρχει φυσική σειρά να τα λύσεις.
Το κόλπο του Bellman-Ford: πρόσθεσε μια δεύτερη παράμετρο που αυξάνει πάντα μονότονα — το πλήθος των ακμών που επιτρέπεται να χρησιμοποιεί η διαδρομή. Αυτό δεν μπλέκεται ποτέ σε κύκλο: μια διαδρομή με ακμές χτίζεται πάντα πάνω σε μία με ακμές. Να η σειρά που έλειπε.
Σταθεροποιούμε έναν προορισμό και ορίζουμε:
Έστω το βέλτιστο τέτοιο μονοπάτι. Δύο περιπτώσεις:
- Το χρησιμοποιεί το πολύ ακμές — τότε .
- Το χρησιμοποιεί ακριβώς ακμές. Έστω η πρώτη του ακμή· το υπόλοιπο είναι το συντομότερο μονοπάτι με ακμές. Κόστος: .
Ο αλγόριθμος
- Είσοδος:
- κατευθυνόμενο γράφημα με βάρη (ίσως αρνητικά), και προορισμός t
- Έξοδος:
- η συντομότερη απόσταση από κάθε κορυφή v προς το t
Με λόγια. Ξεκινάμε με και για κάθε άλλη κορυφή. Σε κάθε από τους γύρους, για κάθε κορυφή δοκιμάζουμε να βελτιώσουμε την απόστασή της μέσω κάθε εξερχόμενης ακμής . Μετά τον γύρο , ο πίνακας περιέχει τις συντομότερες διαδρομές με το πολύ ακμές — οπότε μετά από γύρους έχουμε τις τελικές αποστάσεις.
Πολυπλοκότητα. γύροι, και κάθε γύρος εξετάζει κάθε ακμή μία φορά → χρόνος, χώρος.
Δες τους γύρους να γεμίζουν τον πίνακα. Πρόσεξε ιδιαίτερα το : μετά τον γύρο είναι ακριβώς το καλύτερο μονοπάτι με το πολύ ακμές — γι' αυτό πέφτει σταδιακά, , ανακαλύπτοντας κάθε γύρο ένα μονοπάτι με μία ακμή παραπάνω:
Ζητάμε τις συντομότερες αποστάσεις προς το t. M[i, v] = καλύτερο v→t μονοπάτι με ≤ i ακμές.
Πορτοκαλί = βελτιώθηκε σε αυτόν τον γύρο · πράσινο = η τελική απόσταση s→t.
Βελτιώσεις
Με αυτές: χώρος, χρόνος στη χειρότερη περίπτωση — αλλά συχνά πολύ ταχύτερα.
Κλείδωσε τη γνώση
Βάλε στη σειρά τα βήματα του Bellman-Ford:
Και συμπλήρωσε τα κενά:
Μοτίβο σκέψης
Τι μάθαμε
Τι κρατάμε από αυτή τη διάλεξη
- Ανεξάρτητο σύνολο σε δέντρα — DP με υποπροβλήματα τα υποδέντρα. Δύο τιμές ανά κορυφή: (η ελεύθερη) και (η έξω). , . .
- Ο Dijkstra αποτυγχάνει με αρνητικά βάρη· η προσθήκη σταθεράς δεν βοηθάει.
- Αρνητικός κύκλος → δεν υπάρχει συντομότερη διαδρομή· αλλιώς υπάρχει και είναι απλή ( ακμές).
- Bellman-Ford — = συντομότερο μονοπάτι με ακμές. Αναδρομή: . Απάντηση στο .
- χρόνος· με μονοδιάστατο πίνακα, παράλειψη αμετάβλητων κορυφών και πρόωρο τερματισμό → χώρος.
Ασκήσεις από εξετάσεις
Από τη θεωρία στην εξεταστική
19 άσκησεις που χρησιμοποιούν ως τελευταίο εργαλείο αυτή τη διάλεξη. Οι πρόσφατες εξεταστικές (2024/2025) φέρουν badge προτεραιότητας.
Ιούνιος 2025 · Θέμα 2.1 — Ανίχνευση αρνητικού κύκλου
Ποιον αλγόριθμο χρησιμοποιούμε για να αποφασίσουμε αν ένα κατευθυνόμενο γράφημα έχει αρνητικό κύκλο; (Αρκεί να τον αναφέρεις ονομαστικά.)
Σεπτέμβριος 2024 · Θέμα 1.3 — Σ/Λ: ο Bellman-Ford είναι άπληστος;
Χαρακτήρισε (Σ)ωστό ή (Λ)άθος: «Ο αλγόριθμος Bellman-Ford ανήκει στην κατηγορία των άπληστων αλγορίθμων.»
Φροντιστηριακό Σετ #8 · Άσκηση 1 — Μέσο κόστος όλων των μονοπατιών σε DAG
Εύρεση του μέσου κόστους όλων των μονοπατιών, σε έναν κατευθυνόμενο ακυκλικό γράφο με βάρη , από μία κορυφή έναρξης προς μία κορυφή .
Φροντιστηριακό Σετ #9 — υπό μεταγραφή
Εκφώνηση δεν έχει ακόμα μεταγραφεί.
Φροντιστηριακό Σετ #10 — υπό μεταγραφή
Εκφώνηση δεν έχει ακόμα μεταγραφεί.
Εξ αποστάσεως 2020 — υπό μεταγραφή
Εκφώνηση δεν έχει ακόμα μεταγραφεί.
Φεβρουάριος 2016 — υπό μεταγραφή
Εκφώνηση δεν έχει ακόμα μεταγραφεί.
Φεβρουάριος 2017 — υπό μεταγραφή
Εκφώνηση δεν έχει ακόμα μεταγραφεί.
Φεβρουάριος 2019 — υπό μεταγραφή
Εκφώνηση δεν έχει ακόμα μεταγραφεί.
Ιούνιος 2010 — υπό μεταγραφή
Εκφώνηση δεν έχει ακόμα μεταγραφεί.
Ιούνιος 2011 — υπό μεταγραφή
Εκφώνηση δεν έχει ακόμα μεταγραφεί.
Ιούνιος 2015 — υπό μεταγραφή
Εκφώνηση δεν έχει ακόμα μεταγραφεί.
Ιούνιος 2016 — υπό μεταγραφή
Εκφώνηση δεν έχει ακόμα μεταγραφεί.
Ιούνιος 2018 — υπό μεταγραφή
Εκφώνηση δεν έχει ακόμα μεταγραφεί.
Ιούνιος 2021 — υπό μεταγραφή
Εκφώνηση δεν έχει ακόμα μεταγραφεί.
Σεπτέμβριος 2011 — υπό μεταγραφή
Εκφώνηση δεν έχει ακόμα μεταγραφεί.
Σεπτέμβριος 2017 — υπό μεταγραφή
Εκφώνηση δεν έχει ακόμα μεταγραφεί.
Σεπτέμβριος 2020 — υπό μεταγραφή
Εκφώνηση δεν έχει ακόμα μεταγραφεί.
Σεπτέμβριος 2022 — υπό μεταγραφή
Εκφώνηση δεν έχει ακόμα μεταγραφεί.