This book serves as an introduction to graph theory and its applications. It is intended for a senior undergraduate course in graph theory but is also appropriate for beginning graduate students in science or engineering. The book presents a rigorous (proof-based) introduction to graph theory while also discussing applications of the results for solving real-world problems of interest. The book is divided into four parts. Part 1 covers the combinatorial aspects of graph theory including a discussion of common vocabulary, a discussion of vertex and edge cuts, Eulerian tours, Hamiltonian paths and a characterization of trees. This leads to Part 2, which discusses common combinatorial optimization problems. Spanning trees, shortest path problems and matroids are all discussed, as are maximum flow problems. Part 2 ends with a discussion of graph coloring and a proof of the NP-completeness of the coloring problem. Part 3 introduces the reader to algebraic graph theory, and focuses on Markov chains, centrality computation (e.g., eigenvector centrality and page rank), as well as spectral graph clustering and the graph Laplacian. Part 4 contains additional material on linear programming, which is used to provide an alternative analysis of the maximum flow problem. Two appendices containing prerequisite material on linear algebra and probability theory are also provided.