\newpage
\subsection{All-Pair Shortest Paths}
We can also use $n$-times dijkstra or any other shortest path algorithm, or any of the dedicated ones

\subsubsection{Floyd-Warshall Algorithm}
\begin{definition}[]{Floyd-Warshall Algorithm}
    The \textbf{Floyd-Warshall Algorithm} is a dynamic programming algorithm used to compute the shortest paths between all pairs of vertices in a weighted graph.
\end{definition}


\begin{algo}{FloydWarshall(G)}
    \Procedure{Floyd-Warshall}{$G = (V, E)$}
        \State Initialize distance matrix $d[i][j]$: $d[i][j] =
            \begin{cases}
                0       & \text{if } i = j        \\
                w(i, j) & \text{if } (i, j) \in E \\
                \infty  & \text{otherwise}
            \end{cases}$
        \For{each intermediate vertex $k \in V$}
            \For{each pair of vertices $i, j \in V$}
                \State $d[i][j] \gets \min(d[i][j], d[i][k] + d[k][j])$
            \EndFor
        \EndFor
        \State \textbf{Return} $d$
    \EndProcedure
\end{algo}

\begin{properties}[]{Characteristics of Floyd-Warshall Algorithm}
    \begin{itemize}
        \item \textbf{Time Complexity:} $\tco{|V|^3}$.
        \item Works for graphs with negative edge weights but no negative weight cycles.
        \item Computes shortest paths for all pairs in one execution.
    \end{itemize}
\end{properties}

\begin{usage}[]{Floyd-Warshall Algorithm}
    The Floyd-Warshall algorithm computes shortest paths between all pairs of vertices in a weighted graph (handles negative weights but no negative cycles).

    \begin{enumerate}
        \item \textbf{Initialize:}
              \begin{itemize}
                  \item Create a distance matrix \(D\), where \(D[i][j]\) is the weight of the edge from vertex \(i\) to vertex \(j\), or infinity if no edge exists. Set \(D[i][i] = 0\).
              \end{itemize}

        \item \textbf{Iterate Over Intermediate Vertices:}
              \begin{itemize}
                  \item For each vertex \(k\) (acting as an intermediate vertex):
                        \begin{itemize}
                            \item Update \(D[i][j]\) for all pairs of vertices \(i, j\) using:
                                  \[
                                      D[i][j] = \min(D[i][j], D[i][k] + D[k][j])
                                  \]
                        \end{itemize}
              \end{itemize}

        \item \textbf{Repeat:}
              \begin{itemize}
                  \item Repeat for all vertices as intermediate vertices (\(k = 1, 2, \ldots, n\)).
              \end{itemize}

        \item \textbf{End:}
              \begin{itemize}
                  \item The final distance matrix \(D\) contains the shortest path distances between all pairs of vertices.
              \end{itemize}
    \end{enumerate}
\end{usage}



\newpage
\subsubsection{Johnson's Algorithm}
\begin{definition}[]{Johnson's Algorithm}
    The \textbf{Johnson’s Algorithm} computes shortest paths between all pairs of vertices in a sparse graph. It uses the Bellman-Ford algorithm as a preprocessing step to reweight edges and ensures all weights are non-negative.
\end{definition}

\begin{properties}[]{Characteristics of Johnson's Algorithm}
    \begin{itemize}
        \item \textbf{Steps:}
              \begin{enumerate}
                  \item Add a new vertex $s$ with edges of weight $0$ to all vertices.
                  \item Run Bellman-Ford from $s$ to detect negative cycles and compute vertex potentials.
                  \item Reweight edges to remove negative weights.
                  \item Use Dijkstra's algorithm for each vertex to find shortest paths.
              \end{enumerate}
        \item \textbf{Time Complexity:} $\tco{|V| \cdot (|E| + |V| \log |V|)}$.
        \item Efficient for sparse graphs compared to Floyd-Warshall.
    \end{itemize}
\end{properties}

\begin{usage}[]{Johnson's Algorithm}
    Johnson's algorithm computes shortest paths between all pairs of vertices in a weighted graph (handles negative weights but no negative cycles).

    \begin{enumerate}
        \item \textbf{Add a New Vertex:}
              \begin{itemize}
                  \item Add a new vertex \(s\) to the graph and connect it to all vertices with zero-weight edges.
              \end{itemize}

        \item \textbf{Run Bellman-Ford:}
              \begin{itemize}
                  \item Use the Bellman-Ford algorithm starting from \(s\) to compute the shortest distance \(h[v]\) from \(s\) to each vertex \(v\).
                  \item If a negative-weight cycle is detected, stop.
              \end{itemize}

        \item \textbf{Reweight Edges:}
              \begin{itemize}
                  \item For each edge \(u \to v\) with weight \(w(u, v)\), reweight it as:
                        \[
                            w'(u, v) = w(u, v) + h[u] - h[v]
                        \]
                  \item This ensures all edge weights are non-negative.
              \end{itemize}

        \item \textbf{Run Dijkstra's Algorithm:}
              \begin{itemize}
                  \item For each vertex \(v\), use Dijkstra's algorithm to compute the shortest paths to all other vertices.
              \end{itemize}

        \item \textbf{Adjust Back:}
              \begin{itemize}
                  \item Convert the distances back to the original weights using:
                        \[
                            d'(u, v) = d'(u, v) - h[u] + h[v]
                        \]
              \end{itemize}

        \item \textbf{End:}
              \begin{itemize}
                  \item The resulting shortest path distances between all pairs of vertices are valid.
              \end{itemize}
    \end{enumerate}
\end{usage}



\subsubsection{Comparison}
\begin{table}[h!]
    \centering
    \begin{tabular}{lccc}
        \toprule
        \textbf{Algorithm}  & \textbf{Primary Use}  & \textbf{Time Complexity}      & \textbf{Remarks}         \\
        \midrule
        Floyd-Warshall      & AP-SP                 & $\tco{|V|^3}$                   & Handles negative weights \\
        Johnson’s Algorithm & AP-SP (sparse graphs) & $\tco{|V|(|E| + |V| \log |V|)}$ & Requires reweighting     \\
        \bottomrule
    \end{tabular}
    \caption{Comparison of the All-Pair Shortest path (AP-SP) algorithms discussed in the lecture}
\end{table}
