% This document is licensed under GPL3, a copy of which can be found under
% https://www.gnu.org/licenses/gpl-3.0.txt
% (c) Gilles Englebert 2023-*

\documentclass[11pt]{beamer}
\usetheme{Berkeley}
\usepackage[utf8]{inputenc}
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{amssymb}
\usepackage{graphicx}
\usepackage{listings}
\definecolor{ForestGreen}{RGB}{34,139,34}
\newcommand{\red}[1]{\textcolor{red}{#1}}
\def\e#1\e{\begin{equation}#1\end{equation}}
\def\ea#1\ea{\begin{align}#1\end{align}}
\def\eas#1\eas{\begin{align*}#1\end{align*}}
\def\eq#1{{\rm(\ref{#1})}}
\def\ha{{\ts\frac{1}{2}}}
\def\md#1{\vert #1 \vert}
\def\bmd#1{\big\vert #1 \big\vert}
\def\ms#1{\vert #1 \vert^2}
\def\nm#1{\Vert #1 \Vert}
\def\N{{\mathbin{\mathbb N}}}

\lstdefinestyle{mystyle}{
    commentstyle=\color{ForestGreen},
    keywordstyle=\color{blue},
    numberstyle=\tiny\color{gray},
    stringstyle=\color{codepurple},
    basicstyle=\ttfamily\footnotesize,
    breakatwhitespace=false,         
    breaklines=true,                 
    captionpos=b,                    
    keepspaces=true,                 
    numbers=left,                    
    numbersep=5pt,                  
    showspaces=false,                
    showstringspaces=false,
    showtabs=false,                  
    tabsize=2
}
\lstset{style=mystyle}

\author{Gilles Englebert}
\title{Minimum Spanning Trees}
%\setbeamercovered{transparent} 
%\setbeamertemplate{navigation symbols}{} 
%\logo{} 
\institute{Slides at englebert.lu}
%\date{} 
%\subject{} 
\begin{document}

\begin{frame}
\titlepage
\end{frame}

\begin{frame}
\tableofcontents
\end{frame}

\section{Definitions}
\begin{frame}{Definitions}
Given a graph $(G,V)$ with weighted edges, what is the most efficient way to choose a subset of these edges so that any two vertices are connected? $\Rightarrow$ \textbf{Minimum spanning tree (MST)}.
\begin{center}
\includegraphics[scale=0.14]{Graphmst.png}
\end{center}

\pause
\textbf{Note}: must be a tree, since we can always remove edges from cycles.
\pause
\linebreak
\textbf{Alternatively:} It is also the set of edges that minimizes the largest edge needed to traverse between any two vertices (see Kruskal).

\end{frame}
\section{Algorithms}
\begin{frame}{How to compute MST}

How can we compute a minimum spanning tree (not necessarily unique)? There are two main algorithms:
\pause
\begin{itemize}
\item Prim's algorithm runs in $O(\md{E} \log \md{V})$ and is structurally similar to Dijkstra's algorithm.
\pause
\item Kruskal's algorithm also runs in $O(\md{E} \log \md{V})$ and relies on a \textbf{union-find} data structure.
\end{itemize}

\end{frame}
\subsection{Prim's algorithm}
\begin{frame}[fragile]{Prim's algorithm }
\textbf{Idea}: Start with a single node and no edges. Greedily build the graph by at each step adding the node which has smallest distance to the tree so far constructed.
\pause
\begin{lstlisting}[language=C++]
int prim() {
	int cost = 0;
	int dist[V+1] = {0}, intree[V+1] = 0;
	
	dist [1] = 0;
	intree [1] = 1;

	priority_queue <pair > q;
	q.push(pair(0, -1, 1)); //dist, prev, node
	while (!q.empty()) {
		// Remove closest node , add to tree
		//Add neighbours to queue
	}
	return cost;
}
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]{Prim's algorithm }
\begin{lstlisting}[language=C++]
while (!q.empty()) {
	(d, prev, cur) = q.top(); q.pop();

	if (intree[cur] == 0) { 
		intree[cur] = 1;
		cost += weight(prev, cur); 
	} 
	
	for (int i = 0; i < nb[cur].size(); i++)	
		q.push((nb[cur][i][1], cur, nb[cur][i][0]));
}
\end{lstlisting}
\end{frame}

\begin{frame}{Execution Example}
\includegraphics[scale=0.2]{Prim1.png}
\pause
\includegraphics[scale=0.2]{Prim2.png}
\end{frame}

\subsection{Kruskal's algorithm}
\begin{frame}{Kruskal's algorithm}
\textbf{Idea}: Build the tree by repeatedly adding the smallest edge that does not create a cycle. 
\begin{center}
\includegraphics[scale=0.2]{Kruskal1.png}
\end{center}
\pause \textbf{Note:} checking the cycle condition needs to be done efficiently for this algorithm to be worthwhile. We will need the \textbf{Union-Find} data structure. \pause But first an example.
\end{frame}

\begin{frame}{Execution Example}
\includegraphics[scale=0.3]{Kruskal1.png}
\pause
\includegraphics[scale=0.3]{Kruskal2.png}
\end{frame}

\begin{frame}{Execution Example}
\includegraphics[scale=0.28]{Kruskal3.png}
\pause
\includegraphics[scale=0.3]{Kruskal4.png}
\end{frame}
\subsubsection{Excursion: Union-Find}
\begin{frame}{Union-Find data structure}
Need to determine quickly if if an edge runs within a connected component of a graph or if it connects different connected components, and we need to combine connected components. \pause Formally, we need the following to be fast:
\begin{itemize}
\item $union(x,y)$: Combine connected components of $x$ and $y$.
\item $find(x)$: Identify the connected component of $x$.
\end{itemize}
\pause
At the start, each element is its own connected component.

\end{frame}
\begin{frame}{Idea}
The idea is to have a pointer $p[x]$ for each vertex that points to a representative of the connected component. At the start we have $p[x] =x$.
\begin{center}
\includegraphics[scale=0.2]{UF1.png}
\end{center}
\pause
Then if we call $union(1,2)$ we change the pointer of $2$ to point to $1$.
\begin{center}
\includegraphics[scale=0.2]{UF2.png}
\end{center}
\pause
The function $find(x)$ follows the pointers $p[x]$ until it hits a fixed point (i.e. $p[x] = x$). This is the representative.
\end{frame}
\begin{frame}[fragile]{Algorithm}
\begin{lstlisting}[language=C++]
int p[V];

int find(int a) {
    if (p[a] != a)
        p[a] = find(p[a]); //shortens next search
    return p[a];
}

void unify(int a, int b) { //union is a keyword 
    if (find(b) != find(a))
        p[find(b)] = find(a);
}
\end{lstlisting}
\pause
\textbf{Runtime}: Union has the same runtime as Find. Find could be $O(n)$ in the worst possible case of a long chain. However this is rare thanks to line 5. The \textit{expected} runtime is $O(\alpha(n))$, where $\alpha: \N \rightarrow \N$ is the \textbf{inverse Ackermann function}. It is increasing, but $\alpha(10^{80}) =5$, so \textit{almost} constant.
\end{frame}


\begin{frame}[fragile]{Kruskal}
\begin{lstlisting}[language=C++]
struct TEdge {
	int a, b, w;
} e[E];
int kruskal() {
	sort(e.begin(), e.end(), cmp);  //sorts by weight
	
	int cost = 0;
	for (int i = 0; i < e.size(); i++) {
		if (find(e[i].a) == find(e[i].b))
			continue;
		unify(e[i].a, e[i].b);
		cost += e[i].w;
	}
	return cost;
}
\end{lstlisting}

\end{frame}


\section{Problems}

\begin{frame}{Toy Design}
\textbf{Statement}: Determine the connected components of a graph with $N$ vertices by asking "Is node $x$ connected to node $y$?" at most $Q$ times. Each time the question is answered negatively, a new graph is created where $x$ and $y$ are connected by a further edge. The question can be asked for any one of the graphs created up to that point.

\textbf{Subtasks}
\begin{itemize}
\item $N \le 200$, $Q \le 20000$.
\item $N \le 8$, $Q \le 20$.
\item $N \le 200$, $Q \le 2000$.
\item $N \le 200$, $Q \le 1350$.
\end{itemize}

\end{frame}
\begin{frame}{Homework}
Problems to look at:
\begin{itemize}
\item onlinejudge.org (793 Network Connections, 11631 Dark roads, Transportation system 11228)
\item EGOI '22 Toy Design (Not directly related to MST, but inspired by Union-Find)
\item LIO '15 Reseaux
\end{itemize}

\end{frame}
\end{document}