\newsection
\section{Graphs}

\subsection{Repetition}
The graph algorithms of Kruskal, Prim, Boruvka, Dijkstra, Bellman-Ford, Floyd-Warshall and Johnson are still of importance. See A \& D summary for them

\begin{definition}[]{$\alpha$-approximation algorithm}
    This kind of algorithm approximates the result to level $\alpha$, where $\alpha$ is the factor by which the result is off. Ideally, $\alpha = 1$, for a perfect approximation, which in reality is hardly ever, if ever possible.
\end{definition}


\setcounter{subsection}{3}
\subsection{Connectivity}
\setcounter{all}{23}
% Page 37
\begin{definition}[]{$k$-Connected graph}
    A graph $G = (V, E)$ is called $k$\textit{-connected} if $|V| \geq k + 1$ and for all subsets $X \subseteq V$ with $|X| < k$ we have that the graph $G[V\backslash X]$ is connected
\end{definition}
If $G[V\backslash X]$ is \bi{not} connected, we call it a \textit{(vertex)-separator}.

A $k$-connected graph is also $k - 1$ connected, etc

\begin{definition}[]{$k$-edge-connected}
    A graph $G = (V, E)$ is called $k$\textit{-edge-connected} if for all subsets $X \subseteq E$ with $|X| < k$ we have: The graph $(V, E\backslash X)$ is connected
\end{definition}
We also have \textit{edge-separators}, defined analogously to above, i.e. the set $X$ above is called a $u$-$v$-edge-separator if by removing it from the graph, $u$ and $v$ no longer lay in the same connected component.

If a graph is $k$-edge-connected, it is also $k - 1$-edge-connected, etc


\begin{theorem}[]{Menger's theorem}
    Let $G = (V, E)$ be a graph and $u \neq v \in V$. Then we have
    \begin{enumerate}
        \item Every $u$-$v$-vertex-separator has size at least $k \Leftrightarrow$ Exist at least $k$ internally vertex-disjoint $u$-$v$-paths
        \item Every $u$-$v$-edge-separator has size at least $k \Leftrightarrow$ Exist at least $k$ edge-disjoint $u$-$v$-paths
    \end{enumerate}
\end{theorem}


\newpage
\subsubsection{Articulation points}
If a graph is connected, but not $2$-connected, there exists at least one vertex $v$ for which, if removed, the graph is not connected, called \textit{articulation points}. Using a modified DFS, we can find these vertices. Instead of just setting a flag for each vertex we visit, we set a number indicating the order in which the vertices were visited. The first vertex we visit, for instance, gets number $1$.

We also add another value, which we call \verb|low[v]| $:=$ the smallest DFS-number that can be reached from $v$ using a path of arbitrarily many edges of the DFS-tree and at most one residual edge.

We also have (where $s$ is the start / source vertex and $E(T)$ is the edge set of the DFS-tree):

$v$ is an articulation point $\Leftrightarrow$ ($v = s$ and $s$ has degree at least $2$ in $T$) or ($v \neq s$ and there exists $w \in V$ with $\{(v, w)\} \in E(T)$ and $\verb|low[w]| \geq \verb|dfs[v]|$)


\begin{algorithm}
    \caption{\textsc{FindArticulationPoints}($G, s$)}
    \begin{algorithmic}[1]
        \State $\forall v \in V$: \texttt{dfs[v]}$\gets 0$ \Comment{Stores dfs number for vertex $v$ and also flag for visit}
        \State $\forall v \in V$: \texttt{low[v]}$\gets 0$ \Comment{Stores low point for vertex $v$}
        \State $\forall v \in V$: \texttt{isArticulationPoint[v]}$\gets \texttt{false}$ \Comment{Indicates if vertex $v$ is articulation point}
        \State \texttt{num} $\gets 0$
        \State $T \gets \emptyset$ \Comment{Depth-First-Search Tree}
        \State \Call{DFS-Visit}{$G, s$}
        \If{$s$ has degree at least two in $T$} \Comment{Start vertex classification could be incorrect from \textsc{DFS-Visit}}
            \State $\texttt{isArticulationPoint[s]} \gets \texttt{true}$
        \Else
            \State $\texttt{isArticulationPoint[s]} \gets \texttt{false}$
        \EndIf
        \Procedure{DFS-Visit}{$G, v$}
            \State \texttt{num} $\gets$ \texttt{num} $+ 1$
            \State \texttt{dfs[v]} $\gets$ \texttt{num}
            \State \texttt{low[v]} $\gets$ \texttt{dfs[v]}
            \For{\textbf{all} $\{v, w\} \in E$}
                \If{\texttt{dfs[w]} = 0}
                    \State $T \gets T \cup \{\{v, w\}\}$
                    \State $\texttt{val} \gets$ \Call{DFS-Visit}{$G, w$}
                    \If{$\texttt{val} \geq \texttt{dfs[v]}$} \Comment{Check articulation point condition}
                        \State $\texttt{isArticulationPoint[v]} \gets \texttt{true}$
                    \EndIf
                    \State $\texttt{low[v]} \gets \min \{\texttt{low[v]}, \texttt{val}\}$
                \ElsIf{$\texttt{dfs[w]} \neq 0$ \textbf{and} $\{v, w\} \notin T$} \Comment{Update low if already visited}
                    \State $\texttt{low[v]} \gets \min \{\texttt{low[v]}, \texttt{dfs[w]}\}$
                \EndIf
            \EndFor
            \State \Return \texttt{low[v]}
        \EndProcedure
    \end{algorithmic}
\end{algorithm}

\stepcounter{all}
\begin{theorem}[]{Articulation points Computation}
    For a connected graph $G = (V, E)$ that is stored using an adjacency list, we can compute all articulation points in \tco{|E|}
\end{theorem}


\newpage
\subsubsection{Bridges}
While articulation points show that a graph is not $2$-connected, bridges shows that a graph isn't $2$-edge-connected.
In other words, they are certificates for the graph \textit{not} being $2$-edge-connected or more formally:

\begin{center}
    \fbox{
        \textit{
            An edge $e \in E$ in a connected graph $G = (V, E)$ is called a bridge if the graph $(V, E\backslash \{e\})$ is not connected.
        }
    }
\end{center}

From the definition of bridges we immediately have that a spanning tree has to contain all bridges of a graph, and we can also state that only edges of a Depth-First-Search-Tree are possible candidates for a bridge.

The idea now is that every vertex contained in a bridge is either an articulation point or has degree $1$ in $G$. Or more formally:

\begin{center}
    \fbox{
        \textit{
            A directed edge $(v, w)$ of Depth-First-Search-Tree $T$ is a bridge if and only if $\texttt{low[w]} > \texttt{dfs[v]}$
        }
    }
\end{center}

\begin{theorem}[]{Bridges Computation}
    For a connected graph $G = (V, E)$ that is stored using an adjacency list, we can compute all bridges and articulation points in \tco{|E|}
\end{theorem}

\subsubsection{Block-Decomposition}
\begin{definition}[]{Block-Decomposition}
    Let $G = (V, E)$ be a connected graph. For $e, f \in E$ we define a relation by
    \begin{align*}
        e \sim f \Longleftrightarrow e = f \text{ or exists a common cycle through $e$ and } f
    \end{align*}
    Then this relation is an equivalence relation and we call the equivalence classes \textit{blocks}, sometimes also known as $2$-connectivity-components
\end{definition}
It is now evident that two blocks, if even, can only intersect in one articulation point.
The Block-Decomposition is given by:
\begin{center}
    \fbox{
        \parbox{15cm}{
            Let $T$ be a bipartite graph (in this case a tree), with $V = A \uplus B$ where $A$ is the set of articulation points of $G$ and $B$ the set of blocks of $G$ (This means that every block in $G$ is a vertex in $V$).

            We connect a vertex $a \in A$ with a block $b \in B$ if and only if $a$ is incident to an edge in $b$.

            $T$ is connected if $G$ is and it is free of cycles if $G$ is free of cycles, since every cycle is translatable to a cycle in $G$
        }
    }
\end{center}
The algorithm to determine bridges and articulation points can again be reused and allows us to determine a Block-Decomposition in linear time.



\newpage
\subsection{Cycles}

\subsubsection{Eulerian cycles / circuits}
\begin{definition}[]{Eulerian cycle}
    A \textit{eulerian cycle} in a graph $G = (V, E)$ is a circuit (closed cycle) that contains each edge exactly once.
    If a graph contains a eulerian cycle, we call it \textit{eulerian}
\end{definition}
If $G$ contains a eulerian cycle, $\deg(v)$ of all vertices $v \in V$ is even. For connected graph, we even have a double-sided implication.

If we combine the entirety of the explanations of pages 43-45 in the script, we reach the following algorithm, where $N_G(v)$ is the function returning the neighbours of vertex $v$ in graph $G$:
\begin{algorithm}
    \caption{\textsc{EulerianCycle}$(G, v_{start})$}
    \begin{algorithmic}[1]
        \Procedure{RandomCycle}{$G, v_{start}$}
            \State $v \gets v_{start}$
            \State $W \gets \langle v \rangle$ \Comment{Prepare the cycle (add the start vertex to it)}
            \While{$N_G(v) \neq \emptyset$}
                \State Choose $v_{next}$ arbitrarily from $N_G(v)$ \Comment{Choose arbitrary neighbour}
                \State Attach $v_{next}$ to the cycle $W$
                \State $e \gets \{v, v_{next}\}$
                \State Delete $e$ from $G$
                \State $v \gets v_{next}$
            \EndWhile
            \State \Return $W$
        \EndProcedure
        \State $W \gets$ \Call{RandomCycle}{$v_{start}$} \Comment{Fast runner}
        \State $v_{slow} \gets$ start vertex of $W$
        \While{$v_{slow}$ is not the last vertex in $W$}
            \State $v \gets$ successor of $v_{slow}$ in $W$
            \If{$N_G(v) \neq \emptyset$}
                \State $W' \gets$ \Call{RandomCycle}{v}
                \State $W \gets W_1 + W' + W_2$ \Comment{We union the different branches of the Euler cycle}
            \EndIf
            \State $v_{slow} \gets$ successor of $v_{slow}$ in $W$
        \EndWhile
        \State \Return $W$
    \end{algorithmic}
\end{algorithm}

\begin{theorem}[]{Eulerian Graph}
    \begin{enumerate}[label=\alph*)]
        \item A connected graph $G$ is eulerian if and only if the degree of all vertices is even
        \item In a connected eulerian graph, we can find a eulerian cycle in \tco{|E|}
    \end{enumerate}
\end{theorem}


\newpage
\subsubsection{Hamiltonian Cycles}
\begin{definition}[]{Hamiltonian Cycle}
    A \textit{Hamiltonian Cycle} in a graph $G = (V, E)$ is a cycle passing through each vertex \textit{exactly once}.
    If a graph contains a Hamiltonian cycle, we call it \textit{Hamiltonian}
\end{definition}
A classic example here is the Travelling Salesman Problem (TSP), covered later on.

The issue with Hamiltonian cycles is that the problem is $\mathcal{N}\mathcal{P}$-complete, thus it is assumed that there does not exist an algorithm that can determine if a graph is Hamiltonian in polynomial time.

\stepcounter{all}
\begin{theorem}[]{Hamiltonian Cycle Algorithm}
    The algorithm \textsc{HamiltonianCycle} is correct and has space complexity \tco{n \cdot 2^n} and time complexity \tco{n^2 \cdot 2^n}, where $n = |V|$
\end{theorem}

In the below algorithm, $G = (V, E)$ is a graph for which $V = [n]$ and $N(v)$ as usual the neighbours of $v$ and we define $S$ as a subset of the vertices of $G$ with $1 \in S$.
We define
\begin{align*}
    P_{S, x} := \begin{cases}
                    1 & \text{exists a $1$-$x$-path in $G$ that contains exactly the vertices of $S$} \\
                    0 & \text{else}
                \end{cases}
\end{align*}
We then have:
\begin{align*}
    G \text{ contains a Hamiltonian cycle } \Longleftrightarrow \exists x \in N(1) \text{ with } P_{[n], x} = 1
\end{align*}
Or in words, a graph contains a Hamiltonian Cycle if and only if for any of the neighbours of vertex $1$, our predicate $P_{S, x} = 1$ for $S = V = [n]$ and $x$ being that vertex in the neighbours set $N(1)$.

This means, we have found a recurrence relation, albeit an exponential one.
\begin{algorithm}
    \caption{\textsc{HamiltonianCycle}$(G=([n], E))$}
    \begin{algorithmic}[1]
        \For{\textbf{all} $x \in [n], x \neq 1$} \Comment{Initialization}
            \State $\displaystyle P_{\{1, x\}, x} :=
                \begin{cases}
                    1 & \text{if } \{1, x\} \in E \\
                    0 & \text{else}
                \end{cases}$
        \EndFor

        \For{$s = 3, \ldots, n$} \Comment{Recursion}
            \For{\textbf{all} $S \subseteq [n]$ with $1 \in S$ and $|S| = s$} \Comment{See implementation notes in Section \ref{sec:implementation}}
                \For{\textbf{all} $x \in S, x\neq 1$} \Comment{Fill table for all $x$ in the subset}
                    \State $P_{S, x} = \max\{P_{S\backslash \{x\}, x'} \divides x' \in S \cap N(x), x' \neq 1\}$
                \EndFor
            \EndFor
        \EndFor

        \If{$\exists x \in N(1)$ with $P_{[n], x} = 1$} \Comment{Check condition}
            \State \Return \verb|true|
        \Else
            \State \Return \verb|false|
        \EndIf
    \end{algorithmic}
\end{algorithm}

\newpage
\fhlc{Cyan}{Improved algorithm}

There are algorithms that can find Hamiltonian cycles without using exponential memory usage.
The concept for that is the inclusion-exclusion principle (more on that in Section \ref{sec:prob-basics})

\begin{theorem}[]{Inclusion-Exclusion-Principle}
    For finite sets $A_1, \ldots, A_n$ ($n \geq 2$) we have
    \begin{align*}
        \left| \bigcup_{i = 1}^n A_i \right| & = \sum_{l = 1}^{n}\left((-1)^{l + 1} \sum_{1 \leq i_1 < \dots < i_l \leq n} |A_{i_1} \cap \ldots \cap A_{i_l}|\right)                                                                                              \\
                                             & = \sum_{i = 1}^{n}|A_i| - \sum_{1 \leq i_1 < i_2 \leq n}|A_{i_1} \cap A_{i_2}| + \sum_{1 \leq i_1 < i_2 < i_3 \leq n} |A_{i_1} \cap A_{i_2} \cap A_{i_3}| - \ldots + (-1)^{n + 1} \cdot |A_1 \cap \ldots \cap A_n|
    \end{align*}
\end{theorem}

Since it is easier to find walks compared to paths, we define for all subsets $S \subseteq [n]$ with $v \notin S$ for a start vertex $s \in V$
\begin{align*}
    W_S := \{ \text{\textit{walks} of length $n$ in $G$ with start and end vertex $s$ that doesn't visit any vertices of }S \}
\end{align*}
We thus reach the following algorithm:
\begin{algorithm}
    \caption{\textsc{CountHamiltionianCycles}$(G = ([n], E))$}
    \begin{algorithmic}[1]
        \State $s \gets 1$ \Comment{Start vertex, can be chosen arbitrarily}
        \State $Z \gets |W_{\emptyset}|$ \Comment{All possible paths with length $n$ in $G$}
        \For{\textbf{all} $S \subseteq [n]$ with $s \notin S$ and $S \neq \emptyset$}
            \State Compute $|W_S|$ \Comment{With adjacency matrix of $G[V\backslash S]$}
            \State $Z \gets Z + (-1)^{|S|}|W_S|$ \Comment{Inclusion-Exclusion}
        \EndFor
        \State $Z \gets \frac{Z}{2}$ \Comment{There are two cycles for each \textit{true} cycle (in both directions, we only care about one)}
        \State \Return $Z$ \Comment{The number of Hamiltonian cycles in $G$}
    \end{algorithmic}
\end{algorithm}

\begin{theorem}[]{Count Hamiltionian Cycles Algorithm}
    The algorithm computes the number of Hamiltonian cycles in $G$ with space complexity \tco{n^2} and time complexity \tco{n^{2.81}\log(n) \cdot 2^n}, where $n = |V|$
\end{theorem}
The time complexity bound comes from the fact that we need \tco{\log(n)} matrix multiplications to compute $|W_S|$, which can be found in entry $(s, s)$ in $(A_S)^n$, where $A_S$ is the adjacency matrix of the induced subgraph $G[V\backslash S]$.
Each matrix multiplication can be done in \tco{n^{2.81}} using Strassen's Algorithm.
The $2^n$ is given by the fact that we have that many subsets to consider.


\newpage
\subsubsection{Special cases}
\stepcounter{all}
\begin{lemma}[]{Bipartite graph}
    If $G = (A \uplus B, E)$ is a bipartite graph with $|A| \neq |B|$, $G$ cannot contain a Hamiltonian cycle
\end{lemma}

A hypercube $H_d$ with dimension $d$ has the vertex set $\{0, 1\}^d$.
Two vertices are connected if and only if their $0$-$1$-sequences differ in exactly one bit.
\begin{center}
    \fbox{
        \textit{
            Every hypercube of dimension $d \geq 2$ has a Hamiltonian cycle
        }
    }
\end{center}
Grid graphs (also known as mesh graphs) are graphs laid out in a (typically) square grid of size $m \times n$
\begin{center}
    \fbox{
        \parbox{15cm}{
            A grid graph contains a Hamiltonian cycle if and only if $n$ or $m$ (or both) are even. If both are odd, there is no Hamiltonian cycle
        }
    }
\end{center}

\stepcounter{all}
\begin{theorem}[]{Dirac}
    If $G$ is a graph with $|V| \geq 3$ vertices, for which every vertex has at least $\frac{|V|}{2}$ neighbours, $G$ is Hamiltonian.
\end{theorem}
In other words, every graph with minimum degree $\frac{|V|}{2}$ is Hamiltonian.



\subsubsection{Travelling Salesman Problem}

Given a graph $K_n$ and a function $\displaystyle l : {[n] \choose 2} \rightarrow \N_0$ that assigns a length to each edge of the graph, we are looking for a Hamiltonian cycle $C$ in $K_n$ with
\begin{align*}
    \sum_{e \in C} l(e) = \min \left\{ \sum_{e \in C'} l(e) \divides C' \text{ is a Hamiltonian cycle in } K_n \right\}
\end{align*}
In words, we are looking for the hamiltonian cycle with the shortest length among all hamiltonian cycles.

\stepcounter{all}
\begin{theorem}[]{Travelling Salesman Problem}
    If there exists for $\alpha > 1$ a $\alpha$-approximation algorithm for the travelling salesman problem with time complexity \tco{f(n)}, there also exists an algorithm that can decide if a graph with $n$ vertices is Hamiltonian in \tco{f(n)}.
\end{theorem}
This obviously means that this problem is also $\mathcal{N}\mathcal{P}$-complete.
If we however use the triangle-inequality $l(\{x, z\}) \leq l(\{x, y\}) + l(\{y, z\}))$, which in essence says that a direct connection between two vertices has to always be shorter or equally long compared to a direct connection (which intuitively makes sense),
we reach the metric travelling salesman problem, where, given a graph $K_n$ and a function $l$ (as above, but this time respecting the triangle-inequality), we are again looking for the same answer as for the non-metric problem.

\begin{theorem}[]{Metric Travelling Salesman Problem}
    There exists a $2$-approximation algorithm with time complexity \tco{n^2} for the metric travelling salesman problem.
\end{theorem}

\shortproof This algorithm works as follows: Assume we have an MST and we walk around the outside of it. 
Thus, the length of our path is $2$ \verb|mst|($K_n, l$). 
If we now use the triangle inequality, we can skip a few already visited vertices and at least not lengthen our journey around the outside of the MST.
Any Hamiltonian cycle can be transformed into an MST by removing an arbitrary edge from it.
Thus, for the optimal length (minimal length) of a Hamiltonian cycle, we have $\text{opt}(K_n, l) \geq \verb|mst|(K_n, l)$. 
If we now double the edge set (by duplicating each edge), then, since for $l(C) = \sum_{e \in C} l(e)$ for our Hamiltonian cycle $C$, we have $l(C) \leq 2 \text{opt}(K_n, l)$, we can simply find a eulerian cycle in the graph in \tco{n}, and since it takes \tco{n^2} to compute an MST, our time complexity is \tco{n^2}


\newpage
\subsection{Matchings}
Matchings are assignment problems, which could take the form of assigning a job to a specific CPU core or system.
That system will have to fulfill the performance requirements of the task, but performance should not be wasted, as there could be a different job with higher performance requirements that would not be processable simultaneously otherwise.

\begin{definition}[]{Matching}
    An edge set $M \subseteq E$ of a graph $G$ is called a \textit{matching} if no vertex of the graph is assigned to more than one vertex, or more formally:
    \begin{align*}
        e \cap f = \emptyset \text{ for all } e, f \in M \text{ with } e \neq f
    \end{align*}
    We call a vertex $v$ \textit{covered} by $M$ if there exists an edge $e \in M$ that contains $v$.

    A matching is called a \textit{perfect matching} if every vertex is covered by an edge of $M$, or equivalently $|M| = \frac{|V|}{2}$
\end{definition}

\stepcounter{all}
\begin{definition}[]{Maxima}
    Given a graph $G$ and matching $M$ in $G$
    \begin{itemize}
        \item $M$ is called a \textit{maxim\underbar{al} matching} (or in German ``inklusionsmaximal'') if we have $M \cup \{e\}$ is no matching for all $e \in E \backslash M$
        \item $M$ is called a \textit{maxim\underbar{um} matching} (or in German ``kardinalitätsmaximal'') if we have $|M| \geq |M'|$ for all matchings $M'$ in $G$
    \end{itemize}
\end{definition}

\subsubsection{Algorithms}
\begin{algorithm}
    \caption{\textsc{Greedy-Matching}$(G)$}
    \begin{algorithmic}[1]
        \State $M \gets \emptyset$
        \While{$E \neq \emptyset$}
            \State choose an arbitrary edge $e \in E$ \Comment{Randomly choose from $E$}
            \State $M \gets M \cup \{e\}$
            \State delete $e$ and all incident edges (to both vertices) in $G$
        \EndWhile
    \end{algorithmic}
\end{algorithm}
The above algorithm doesn't return the maximum matching, just a matching
\begin{theorem}[]{Greedy-Matching}
    The \textsc{Greedy-Matching} determines a maximal matching $M_{Greedy}$ in \tco{|E|} for which we have
    \begin{align*}
        |M_{Greedy}| \geq \frac{1}{2} |M_{\max}|
    \end{align*}
    where $M_{\max}$ is a maximum matching
\end{theorem}

\begin{theorem}[]{Berge's Theorem}
    If $M$ is a not a maximum matching in $G$, there exists an augmenting path to $M$
\end{theorem}
\inlineproof If $M$ is not a maximum matching, there exists a matching $M'$ with higher cardinality, where $M \oplus M'$ ($M$ xor $M'$) has a connected component that contains more edges of $M'$ than $M$. Said connected component is the augmenting path for $M$

This idea leads to an algorithm to determine a maximum matching: As long as a matching isn't a maximum matching, there exists an augmenting path that allows us to expand the matching. After \textit{at most} $\frac{|V|}{2} - 1$ steps, we have a maximum matching. For bipartite graphs, we can use modified BFS with time complexity \tco{(|V| + |E|) \cdot |E|} to determine the augmenting paths.
\begin{algorithm}
    \caption{\textsc{AugmentingPath}$(G = (A \uplus B, E), M)$}
    \begin{algorithmic}[1]
        \State $L_0 := \{ \text{set of all non-covered vertices in $A$} \}$
        \If{$L_0 = \emptyset$}
            \State \Return $M$ is a maximum matching
        \EndIf
        \State Mark all vertices in $L_0$ as visited
        \For{$i = 1, \ldots, n$}
            \If{$i$ is odd} \Comment{We start with an unmatched vertex (by definition)}
                \State $L_i := \{\text{all unvisited neighbours of $L_{i - 1}$ using edges in } E \backslash M\}$
            \Else
                \State $L_i := \{\text{all unvisited neighbours of $L_{i - 1}$ using edges in } M\}$
            \EndIf
            \State Mark all vertices in $L_i$ as visited \Comment{We used them in our augmenting path, note that}
            \If{$L_i$ contains non-covered vertex $v$}
                \State Find path $P$ starting at $L_0$ and ending at $v$ using backtracking
                \State \Return $P$
            \EndIf
        \EndFor
        \State \Return $M$ is already a maximum matching
    \end{algorithmic}
\end{algorithm}
\begin{center}
    \fbox{
        \parbox{15cm}{
            \textbf{Augmenting Path}: An \textit{alternating path} that (here) starts from unmatched vertices, where an alternating path is a path that starts with an unmatched vertex and whose edges alternately belong to the matching and not.
        }
    }
\end{center}
The algorithm discussed above uses layers $L_i$ to find the augmenting paths. Each of the layers is alternatingly part of the matching and not part of it, where the first one is not part of the matching. Augmenting paths also always have length $m$ odd, so the last layer is \textit{not} part of the matching.


\fhlc{Cyan}{Hopcroft and Karp Algorithm}

\begin{algorithm}
    \caption{\textsc{MaximumMatching}$(G = (A \oplus B, E))$}
    \begin{algorithmic}[1]
        \State $M \gets \{e\}$ for any edge $e \in E$ \Comment{Initialize Matching with simple one of just one edge (trivially a matching)}
        \While{there are still augmenting paths in $G$}
            \State $k \gets$ length of the shortest augmenting path
            \State find a maximal set $S$ of pairwise disjunct augmenting paths of length $k$
            \For{\textbf{all} $P$ of $S$}
                \State $M \gets M \oplus P$ \Comment{Augmenting along all paths of $S$}
            \EndFor
        \EndWhile
        \State \Return $M$
    \end{algorithmic}
\end{algorithm}
To find the shortest augmenting path, we observe that if the last layer has more than one non-covered vertex, we can potentially (actually, likely) find more than one augmenting path.
We find one first, remove it from the data structure and find more augmenting paths by inverting the tree structure (i.e. cast \textit{flippendo} on the edges) and using DFS to find the all augmenting paths.
We always delete each visited vertex and we thus have time complexity \tco{|V| + |E|}, since we only visit each vertex and edge once.

\begin{theorem}[]{Hopcroft and Karp Algorithm}
    The algorithm of Hopcroft and Karp's while loop is only executed \tco{\sqrt{|V|}} times.
    Hence, the maximum matching is computed in \tco{\sqrt{|V|} \cdot (|V| + |E|)}
\end{theorem}

\newpage
\fhlc{Cyan}{Other matching algorithms}

In Section 4, using flows to compute matchings is discussed.

\begin{theorem}[]{Weighted Matching problem}
    Let $n$ be even and $l: {[n] \choose 2} \rightarrow \N_0$ be a weight function of a complete graph $K_n$. Then, we can compute, in time \tco{n^3}, a minimum perfect matching with
    \begin{align*}
        \sum_{e \in M} l(e) = \min\left\{ \sum_{e \in M'} l(e) \smallhspace \Big| \smallhspace M' \text{ is a perfect matching in } K_n \right\}
    \end{align*}
\end{theorem}

\begin{theorem}[]{MTSP with approximation}
    There is a $\frac{3}{2}$-approximation algorithm with time complexity \tco{n^3} for the metric travelling salesman problem
\end{theorem}

\subsubsection{Hall's Theorem}
\begin{theorem}[]{Hall's Theorem}
    For a bipartite graph $G = (A \uplus B, E)$ there exists a matching $M$ with cardinality $|M| = |A|$ if and only if
    \begin{align*}
        |N(X)| \geq |X| \smallhspace \forall X \subseteq{A}
    \end{align*}
\end{theorem}
The following theorem follows from Hall's Theorem immediately. We remember that a graph is $k$-regular if and only if every vertex of the graph has degree exactly $k$

\begin{theorem}[]{Matching in $k$-regular bipartite graphs}
    Let $G$ be a $k$-regular bipartite graph. Then there exists $M_1, \ldots, M_k$ such that $E = M_1 \uplus \ldots \uplus M_k$ where each $M_i$ is a perfect matching
\end{theorem}

\begin{theorem}[]{Algorithm for the problem}
    If $G$ is a $2^k$-regular bipartite graph, we can find a perfect matching in time \tco{|E|}
\end{theorem}
It is important to note that the algorithms to determine a perfect matching in bipartite graph do not work for non-bipartite graphs, due to the fact that when we remove every other edge from the eulerian cycle, it is conceivable that the graph becomes disconnected. While this is no issue for bipartite graphs (as we can simply execute the graph on all connected components), for $k = 1$, such a connected component can could contain an odd number of vertices, thus there would be a eulerian cycle of odd length from which not every other edge can be deleted. Since that component has odd length, no perfect matching can exist.

\stepcounter{all}


\newpage
\subsection{Colourings}
Good examples for problems that can be solved using colourings are the channel picking of wireless devices, for compilers to pick registers and for creating timetables and exam schedules.

\begin{definition}[]{Colouring}
    A \textit{(vertex-)colouring} of a graph $G$ with $k$ colours is an image $c: V \rightarrow [k]$ such that
    \begin{align*}
        c(u) \neq c(v) \smallhspace \forall \{u, v\} \in E
    \end{align*}
    The chromatic number $\mathscr{X}(G)$ is the minimum number of colours that are required to colour the graph $G$
\end{definition}
\stepcounter{all}
Graphs with chromatic number $k$ are also called $k$-\textit{partite}, where from the naming of a \textit{bipartite} graph comes, since we can \textit{partition} the graph into $k$ separate sets
\begin{theorem}[]{Bipartite graph}
    A graph $G = (V, E)$ is bipartite if and only if it does not contain a cycle of uneven length as sub-graph
\end{theorem}
On political maps, two neighbouring countries are coloured in different colours.
We assume that the territories of every country is connected and that all countries that only touch at one point can be coloured with the same colour.
\begin{theorem}[]{Four colour theorem}
    Every land map can be coloured in four colours
\end{theorem}
Again, the problem of determining if the chromatic number of a graph is smaller than a value $t$ is another $\mathcal{N}\mathcal{P}$-complete problem. We thus have to again proceed with an approximation.

The following algorithm correctly computes \textit{\textbf{a}} valid colouring.
\begin{theorem}[]{Greedy-Colouring Algorithm}
    For the number of colours $C(G)$ the \textsc{Greedy-Colouring} needs to colour the connected graph $G$ we have
    \begin{align*}
        \mathscr{X}(G) \leq C(G) \leq \Delta(G) + 1
    \end{align*}
    where $\Delta(G) := \max_{v\in V}\deg(v)$ is the maximum degree of a vertex in $G$. If the graph is stored as an adjacency list, the algorithm finds a colouring \tco{|E|}
\end{theorem}

\begin{algorithm}
    \caption{\textsc{Greedy-Colouring}$(G)$}
    \begin{algorithmic}[1]
        \State Choose an arbitrary order of vertices $V = \{v_1, \ldots, v_n\}$
        \State $c[v_1] \gets 1$
        \For{$i = 2, \ldots, n$}
            \State $c[v_i] \gets \min \{k \in \N \divides k \neq c(u) \smallhspace \forall u \in N(v_i) \cap \{v_1, \ldots, v_{i - 1}\}\}$ \Comment{Find minimum available colour}
        \EndFor
    \end{algorithmic}
\end{algorithm}

\begin{theorem}[]{Brook's theorem}
    Let $G$ be a connected graph that is neither complete nor a cycle of uneven length (uneven cycle), we have
    \begin{align*}
        \mathscr{X}(G) \leq \Delta(G)
    \end{align*}
    and there is an algorithm that colours the graph using $\Delta(G)$ colours in \tco{|E|}. Otherwise $\mathscr{X}(G) \leq \Delta(G) + 1$
\end{theorem}
Of note is that a graph with an even number of vertices and edges does not contain an uneven cycle, so for an incomplete graph with an even number of edges and vertices, we always have that $\mathscr{X}(G) \leq \Delta(G)$

\begin{theorem}[]{Maximum degree}
    Let $G$ be a graph and $k \in \N$ the number representing the maximum degree of any vertex of any induced subgraph of $G$. Then we have $\mathscr{X}(G) \leq k + 1$ and a $(k + 1)$-coloring can be found in \tco{|E|}
\end{theorem}

\begin{theorem}[]{Mycielski-Construction}
    For all $k \geq 2$ there exists a triangle-free graph $G_k$ with $\mathscr{X}(G_k) \geq k$
\end{theorem}
It is even possible to show that for all $k, l \geq 2$ there exists a graph $G_{k, l}$ such that said graph doesn't contain a cycle of length \textit{at most} $l$, but we still have $\mathscr{X}(G_{k, l}) \geq k$.

To conclude this section, one last problem:

We are given a graph $G$ which we are told has $\mathscr{X}(G) = 3$. This means, we know that there is exists an order of processing for the \textsc{Greedy-Colouring} algorithm that only uses three colours. We don't know the colours, but we can find an upper bound for the number of colours needed
\begin{theorem}[]{$3$-colourable graphs}
    Every $3$-colourable graph $G$ can be coloured in time \tco{|E|} using at most \tco{\sqrt{|V|}} colours
\end{theorem}
Since the graph has to be bipartite (because for each vertex $v$, its neighbours can only be coloured in $2$ other colours, because the graph can be $3$-coloured), we can use BFS and thus have linear time. The algorithm works as follows: We choose the vertices with the largest degree and apply three colours to them. For the ones of smaller degree, we apply Brook's theorem.
