אלגוריתם APSP הוא אלגוריתם למציאת מסלולים קצרים ביותר בין כל הזוגות בגרף . סוג של הכללה לבעית הSSSP.
קלט: גרף
פשוט
פלט: נרצה להחזיר שתי מטריצות -
א) מטריצת מרחקים
ב) מטריצת קודמים
נשים לב שגם בבעיית המסלולים הקצרים ביותר מקודקוד יחיד התמקדנו בגרפים ללא מעגלים שליליים וכך זה ימשיך פה, נוכל להוסיף לאלגוריתם ״שכבת הגנה״ שבודקת התכנות של מעגלים שליליים בגרף ואם אכן יש כאלו נחזיר שגיאה כלשהי ולא פלט רצוי.
ניתן להריץ את האלגוריתם של בלמן-פורד מכל קודקוד כלומר בזמן
אם אנחנו יודעים שהקשתות אי שליליות - נוכל להריץ מכל קודקוד את האלגוריתם של דייקסטרה ולקבל זמן ריצה עדיף . לפי מבנה הנתונים שהשתמשנו בו כדי להחזיק את קשת החתך המינימלי כאיבר מינימום.
א) מערך:
ב) ערימה בינארית:
ג) ערימת פיבונאצי :
לעתים נרצה לבטא את זמן הריצה ככזה שתלוי רק במשתנה אחד למשל מספר הקודקודים, נזכר שישנו חסם על מספר הקשתות בגרף.
א) אם הגרף דליל sparse-
ב) אם הגרף צפוף dense-

אם הגרף לא ממושקל נוכל להריץ BFS על כל קודקודי הגרף ולפתור את בעיית APSP בזמן ש ל
אלגוריתם המשתמש בתכנות דינמי . נרצה להגדיר נוסחת נסיגה לכל מסלול שכל פעם מתבססת על קלט ״קטן״ יותר של קודקודים בהם ניתן להעזר.
קודקודי ביניים: יהי
נרצה להבין איך מגדירים את נוסחת הנסיגה של האלגוריתם הריקורסיבי ובעצם מהו הפתרון האופטימלי...
לשם הנוחות נניח שקודקודי הגרף ממוספרים (כפי שהגדרנו בהתחלה) ונתבונן בקבוצת הקודקודים
כעת נתבונן בכל המסלולים משתי קודקודים
יהי

נשים לב לשתי מקרים חשובים שיכולים להיות עבור
אם
אם

כעת יש לנו 2 מסלולים
נגדיר
כל המטריצות הן מטריצות מרחקים עבור המסלול עם קבוצת קודקודי הביניים
איך מאכלסים את
נוכל לאכלס כל איבר במטריצות הנ״ל באופן הבא, בזכות למת תת המסלול...
כלומר המינימום בין המקרה ש
כיוון שלכל מסלול קודקודי הביניים הם מהקבוצה
הקלט יהיה מטריצת שכנויות
כלומר במקום לשים ערך בינארי במטריצה , היכן שיש קשת נשים את משקלה. החישוב אם כן, יהיה מההתחלה לסוף, על כל
floyd_warshall(W):
n = W.rows
D[0] = W
for k = 1 to n
D[K] = new matrix[n,n]
for i = 1 to n
for j = 1 to n
d_ij[k] = min(d_ij[k-1], d_ik[k-1]+ d_kj[j-1])
זמן ריצה
שחזור פתרון:
ניתן לחשב את מטריצת הקודמים
יתקיים
ונחשב את מטריצת הקודמים בסדר עולה
נגדיר
מקרה הבסיס הוא
בכל מצב אחר :
נשלב את הפונקצייה בפתרון הנ״ל וזה לא יפריע לזמן הריצה.

האלגוריתם של גונסון פותר את בעיית
דליל -
צפוף -
כמו כן, האלגוריתם של ג׳ונסון מזהה מעגלים שליליים בגרף במידה והיה.
הוא מתבסס על האלגוריתמים של דייקסטרה ובלמן פורד ומשתמש בטכניקה שנקראת שקלול מחדש.
אם ידוע שכל קשתות הגרף אי שליליות אפשר עדיין להריץ את דייקסטרה על כל קודקודי הגרף ולקבל זמן ריצה שקול.
כלומר מההבחנה הזאת , והעובדה שציינו שאנחנו הולכים להשתמש בטכניקה שנקראת שיקלול מחדש, אפשר כבר להבין את הכיוון שאליו אנחנו הולכים. נרצה לחשב פונקציית משקלים חדשה עבור הקשתות של הגרף ששומרת על היחסים המקוריים אבל תגרום לכל הקשתות להיות אי שליליות כדי שנוכל להריץ דייקסטרה.
באופן פורמלי נרצה להגדיר
א)
ב)
נבנה כמה לימות עזר שבאמצעותן נוכל להגדיר פונקציית משקלים חדשה:
למה 1 שקלול מחדש לא משנה את המסלולים הקצרים:
יהי
לכל קשת
יהי
בנוסף,
הוכחה:
הראנו תכונה מעניינת על הפונקצייה החדשה שאנחנו מגדירים כאשר מפעילים אותה על המסלול. בגלל שיש מעין טלסקופיות בטור הנ״ל. לא משנה מיהו המסלול
נשים לב שאם
כלומר המשקלים של כל המעגלים זהים ובפרט אלו השליליים.
למה 2 יצירת משקלים אי שליליים באמצעות שקלול מחדש:
בהינתן גרף מכוון
כעת נניח ש
נרצה להוכיח :
הוכחה:
ראשית נבחין שכיוון שאין קשתות נכנסות ל
כלומר ההנחה שלנו ששתי הגרפים לא מכילים מעגלים שליליים היא נכונה שכן אם אחד מהם מכיל אז גם השני ונוכל לצאת מהאלגוריתם.
לפי אי שיוויון המשולש עבור קשת
שלב ראשון, הוספת הקודקוד s כקודקוד מקור

שלב שני, חישוב מחדש של המשקלים לפי

האלגוריתם:
האלגוריתם של גונסון משתמש בבלמן פורד בשביל לבנות את המסלולים הקצרים ביותר על
johnson(G=(V,E), w):
initialize G'
if bellman-ford(G',w ,s) == false
error : negative cycle
for each u in G.V:
h(u)= 𝜹(s,u)
for each (u,v) in G.E:
w'(u,v) = w(u,v) + h(u) - h(v)
D = new matrix[n,n]
for each v in V
dikstra(G, v, w')
for each u in V
\\the reverse function of w' to get the original w value
d_uv = 𝜹'(u,v) - h(u) + h(v)
return D
זמן הריצה של האלגוריתם שקול ללהריץ פעם אחת בלמן פורד ו