You are on page 1of 102

Bilgisayar Mühendisliği Bölümü

DATA STRUCTURES
AND
ALGORITHMS

Lecture Notes 12
Graphs

Spring 2008

GIT – Computer Engineering Department


Chapter Outline
 Graph Terminology
 The Graph ADT and Edge Class
 Implementing the Graph ADT
 Traversals of Graphs
 Application of Graph Traversals
 Algorithms Using Weighted Graphs

GIT – Computer Engineering Department 2


What is a Graph
 A graph is a set of vertices and a set of edges that
connect pairs of distinct vertices.
 Mathematically, a graph is a tuple G = (V, E) where
– V : set of vertices /nodes
– E : set of edges / links , E ⊂ V×V
• each edge is a pair (v,w ), where v,w Є V
– vertex w is adjacent to v iff (v,w) Є E
 A graph may be directed or undirected.
– If the pairs, (v,w ) are ordered, then the graph is directed
• directed graphs are sometimes refered as digraphs
– In an undirected graph, (u, v) ∈ E iff (v, u) ∈ E
• the edges of an undirected graph are unordered pairs; (u, v) and
(v, u) are the same edge.

GIT – Computer Engineering Department 3


Example
 Visually we represent the vertices as points (or labeled
circles) and the edges as lines joining the vertices
 Ex: An undirected graph G = (V, E) where
V = {A, B, C, D, E}
E = {{A, B}, {A, D}, {C, E}, {D, E}}

A B

D E C

GIT – Computer Engineering Department 4


A Directed Graph
 Ex: A directed graph G = (V, E) where
V = {A, B, C, D, E}
E = {(A, B), (B, A), (B, E), (D, A), (E, A), (E, D), (E, C)}
A B

D E C

The numbering of the vertices, and their physical arrangement are not important.

GIT – Computer Engineering Department 5


Weighted Graph
Ann Arbor (Not To Scale)
260 50
Chicago 40
148 60
Fort Wayne Detroit Cleveland
130 Pittsburgh
Toledo 120
320

180 155 150


120 Philadelphia
180

180
Indianapolis Columbus

GIT – Computer Engineering Department 6


Path in a Graph
 A path is a sequence of vertices in which each successive
vertex is adjacent to its predecessor
– w1, w2, …, wN where (wi, wi+1) Є E for 1≤i<N
 The length of a path is the number of edges on the path,
which is equal to N-1
– if path contains no edges, length is 0
 A simple path is a path such that all vertices are distinct
– except the first and last, they could be same
 A cycle is a simple path in which the first and final vertices
are the same.
– A simple path with length ≥ 1 where w1 = wN
– Cycle is simple, if the path is simple
– In an undirected graph edges should be distinct for simple cycle
 A directed graph is acyclic if it has no cycles
– A directed acyclic graph is refered to DAG

GIT – Computer Engineering Department 7


Example of a Path

Ann Arbor (Not To Scale)


260 50
Chicago 40
148 60
Fort Wayne Detroit Cleveland
130 Pittsburgh
Toledo 120
320

180 155 150


120 Philadelphia
180

180
Indianapolis Columbus

GIT – Computer Engineering Department 8


Example of a Cycle

Ann Arbor (Not To Scale)


260 50
Chicago 40
148 60
Fort Wayne Detroit Cleveland
130 Pittsburgh
Toledo 120
320

180 155 150


120 Philadelphia
180

180
Indianapolis Columbus

GIT – Computer Engineering Department 9


Connected Graph
 An undirected graph is connected if there is a path
between each pair of vertices
 A directed graph is strongly connected if there is a
directed path between each pair of vertices
 A directed graph is weakly connected if the
underlying undirected graph is connected
– undirected path between each pair of vertices
 A complete graph is a graph in which there is an
edge between every pair of vertices

 A graph that is not connected, consists of


connected components

GIT – Computer Engineering Department 10


Disconnected Graph

0 7 8
6
1 2

9 10
3
4
5 11 12

GIT – Computer Engineering Department 11


Relationship Between Graphs and Trees
 A tree is a special case of a graph.
 Any connected graph which does not contain
cycles can be considered a tree.
 Any node can be chosen to be the root.

GIT – Computer Engineering Department 12


Application of Graphs
 Determine network connectivity.
 Schedule courses in accordance with
prerequisite requirements.
 Finding the shortest (or least cost) path.
– Network routing
– Travel planning

GIT – Computer Engineering Department 13


Example: Airport system
 Each airport is a vertex
 Two vertices are connected by an egde if there is a
nonstop flight from the airports that are represented
by the vertices
 Such a graph is directed
 The edge could have a weight, representing time,
distance or cost of flight.
– It might have longer or cost more to fly in different
directions
 Make sure that the airport system is strongly
connected
– It is always possible to fly from any airport to any other

GIT – Computer Engineering Department 14


Example: Traffic Flow
Traffic flow can be modeled by a graph
 Each street intersection represents a vertex,
each street is an edge.
 Edge costs could represent, among other
things, a speed limit or capacity
 We could ask for the shortest route or use this
information to find the most likely location for
bottleneck

GIT – Computer Engineering Department 15


Abstract Representation of a Graph
 We will consider the vertices to be the
integers from 0 to |V|-1.
 Operations on a graph:
– Create a graph of n vertices. No edges.
– Insert an edge
– Remove an edge
– Query the existence of an edge
– Iterate over the vertices adjacent to a given vertex

GIT – Computer Engineering Department 16


Design of the Graph class
Function Behavior
int get_num_v() const Return the number of vertices.
bool is_directed() const Return true if this is a directed graph.
virtual void insert(const Edge&) = 0 Insert a new edge into the graph.
virtual bool is_edge(int source, Determine whether there is an edge
int dest) const = 0 between two vertices.
virtual Edge get_edge(int source, Return the edge between two vertices.
int dest) const = 0
virtual iterator begin(int source) Return an iterator to the first edge
const = 0 adjacent to the specified vertex.
virtual iterator end(int source) Return an iterator one past the last edge
const = 0 adjacent to the specified vertex
void Load the edges of a graph from the
load_edges_from_file(std::istream&) data in an input file.
static Graph* Factory function to create a graph and
create_graph(std::istream&, bool, load the data from an input file.
const std::string&)

GIT – Computer Engineering Department 17


Abstract Graph in C++
/** Abstract class to specify a Graph ADT. A graph is a set
of vertices and a set of edges. Vertices are
represented by integers from 0 to n - 1. Edges
are ordered pairs of vertices.
*/
class Graph {

public:

// Forward declaration of iterator class


class iterator;

// Constructor
/** Construct a graph
@param n The number of vertices
@param d True if this is a directed graph
*/
Graph(int n, bool d) : num_v(n), directed(d) {}

// Virtual Destructor
virtual ~Graph() {}

GIT – Computer Engineering Department 18


Graph.h (2)
// Accessors
int get_num_v() const {return num_v;}

bool is_directed() const {return directed;}

virtual void insert(const Edge& edge) = 0;

virtual bool is_edge(int source, int dest) const = 0;

virtual Edge get_edge(int source, int dest) const = 0;

virtual iterator begin(int source) const = 0;

virtual iterator end(int source) const = 0;

void load_edges_from_file(std::istream& in);

static Graph* create_graph(std::istream& in, bool is_directed,


const std::string& type);

GIT – Computer Engineering Department 19


Graph.h (3)
// Definition of nested classes iter_impl and iterator

protected:

// Data fields
/** The number of vertices */
int num_v;
/** Flag to indicate whether this is a directed graph */
bool directed;

}; // End class Graph

GIT – Computer Engineering Department 20


The Edge Class

Data Field Attribute


int dest The destination vertex
int source The source vertex
double weight The weight.
Constructor Behavior
Edge(int s, int d, double w = 1.0) Constructs an Edge from s to d. Sets the
weight to 1.0 if w is not specified.
Edge() Constructs a dummy edge with source
and destination set to -1 and weight to
infinity.
Edge(const Edge&) Copy constructor.

GIT – Computer Engineering Department 21


The Edge Class (2)

Function Behavior
bool operator==(const Edge& other) Compare two Edges for equality. Edges
are equal if their source and destination
are equal. The weight is not considered.
bool operator!=(const Edge& other) The negation of the equality operator.
int get_dest() const Returns the destination vertex.
int get_source() const Returns the source vertex.
double get_weight() const Returns the weight.
string to_string() const Returns a string representation of the
edge.
ostream& operator<<(ostream&, Overloaded ostream insertion operator.
const Edge&)

GIT – Computer Engineering Department 22


Concrete Representation of a Graph
 Two methods of representing a graph are
popular:
– Adjacency Matrix
– Adjacency List

GIT – Computer Engineering Department 23


Adjacency Matrix Representation
 Use a two dimensional |V| × |V| matrix to represent
a graph
– For each edge (u,v) Є E we set A [u][v] = 1
– A [u][v] = 0 , otherwise
 If the edge has a weight we set A[u][v] = weight
we can use -∞ / ∞ to indicate nonexistent edges
 Space requirement = θ(|V|2)
 An adjacency matrix is an appropriate
representation if the graph is dense: |E| = θ (|V|2)
– is it true in most applications ?

GIT – Computer Engineering Department 24


Adjacency Matrix

0 1
0 1 2 3 4
0 1.0 1.0
2 1 1.0 1.0 1.0 1.0
2 1.0 1.0
3 1.0 1.0 1.0
4 3 4 1.0 1.0 1.0

GIT – Computer Engineering Department 25


Adjacency Matrix (directed graph)

0 1 2 0 1 2 3 4 5
0 1.0 1.0
1 1.0
2 1.0 1.0
3 1.0
4 1.0
3 4 5 5 1.0

GIT – Computer Engineering Department 26


Adjacency List Representation
 A vector (array) of lists
– one for each vertex.
– Each list has the adjacent vertices

 If the graph is not dense (is sparse) a better


solution is adjacency list representation
 The space requirement is O(|E|+|V|)

GIT – Computer Engineering Department 27


Adjacency List (Directed Graph)

GIT – Computer Engineering Department 28


Adjacency List Representation

GIT – Computer Engineering Department 29


Overview of Class Hierarchy

GIT – Computer Engineering Department 30


The create_graph function
Graph* Graph::create_graph(istream& in, bool d,
const std::string& type) {
int n;
in >> n;
in.ignore(numeric_limits<int>::max(), '\n'); // Skip rest of line
Graph* return_value = NULL;
if (type == "Matrix")
return_value = new Matrix_Graph(n, d);
else if (type == "List")
return_value = new List_Graph(n, d);
else
throw std::invalid_argument("Unrecognized Graph Type");
return_value->load_edges_from_file(in);
return return_value;
}

GIT – Computer Engineering Department 31


The iterator class
class iterator {

public:
Edge operator*() { return ptr_to_impl->operator*(); }
iterator& operator++() { ++(*ptr_to_impl); return *this; }
iterator operator++(int)
{ iterator temp(*this); ++(*ptr_to_impl); return temp;}
bool operator==(const iterator& other) const
{ return *ptr_to_impl == *other.ptr_to_impl; }
bool operator!=(const iterator& other) const
{ return !((*this) == other); }
~iterator() {delete ptr_to_impl;}
iterator(const iterator& other) :
ptr_to_impl(other.ptr_to_impl->clone()) {}
iterator(iter_impl* p_impl) : ptr_to_impl(p_impl) {}

private:
/** Pointer to the implementation */
iter_impl* ptr_to_impl;
}; // End iterator

GIT – Computer Engineering Department 32


The iter_impl class
class iter_impl {
public:
virtual Edge operator*() = 0;
virtual iter_impl& operator++() = 0;
virtual bool operator==(const iter_impl&) const = 0;
virtual iter_impl* clone() = 0;
virtual ~iter_impl() {}
};

GIT – Computer Engineering Department 33


Design of the List_Graph class
Data Field Attribute
vector<list<Edge> > edges A vector of lists to contain the edges that
originate with each vertex.
Constructor Purpose
List_Graph(int n, bool d) Constructs a graph with the specified
number of vertices and directionality.
Public Member Functions Behavior
iterator begin(int source) const Returns an iterator to the edges that
originate from a given vertex.
iterator end(int source) const Returns an iterator one past the last edge
that originates from a given vertex.
Edge get_edge(int source, int Gets the edge between two vertices.
dest) const
void insert(const Edge& e) Inserts a new edge into the graph
bool is_edge(int source, int Determines whether an edge exists from
dest) const vertex source to vertex dest.

GIT – Computer Engineering Department 34


Design of the Graph class
Function Behavior
int get_num_v() const Return the number of vertices.
bool is_directed() const Return true if this is a directed graph.
virtual void insert(const Edge&) = 0 Insert a new edge into the graph.
virtual bool is_edge(int source, Determine whether there is an edge
int dest) const = 0 between two vertices.
virtual Edge get_edge(int source, Return the edge between two vertices.
int dest) const = 0
virtual iterator begin(int source) Return an iterator to the first edge
const = 0 adjacent to the specified vertex.
virtual iterator end(int source) Return an iterator one past the last edge
const = 0 adjacent to the specified vertex
void Load the edges of a graph from the
load_edges_from_file(std::istream&) data in an input file.
static Graph* Factory function to create a graph and
create_graph(std::istream&, bool, load the data from an input file.
const std::string&)

GIT – Computer Engineering Department 35


The is_edge and get_edge functions
bool List_Graph::is_edge(int source, int dest) const {
list<Edge>::const_iterator itr = find(edges[source].begin(),
edges[source].end(),
Edge(source, dest));
return itr != edges[source].end();
}

Edge List_Graph::get_edge(int source, int dest) const {


list<Edge>::const_iterator itr = find(edges[source].begin(),
edges[source].end(),
Edge(source, dest));
if (itr != edges[source].end())
return *itr;
else
return Edge(source, dest, numeric_limits<double>::infinity());
}

GIT – Computer Engineering Department 36


The insert function
void List_Graph::insert(const Edge& edge) {
edges[edge.get_source()].push_back(edge);
if (!is_directed()) {
edges[edge.get_dest()].push_back(Edge(edge.get_dest(),
edge.get_source(),
edge.get_weight()));
}
}

GIT – Computer Engineering Department 37


The begin and end functions
Graph::iterator List_Graph::begin(int source) const {
return Graph::iterator(new iter_impl(edges[source].begin()));
}

Graph::iterator List_Graph::end(int source) const {


return Graph::iterator(new iter_impl(edges[source].end()));
}

GIT – Computer Engineering Department 38


The List_Graph::iter_impl class
class iter_impl : public Graph::iter_impl {
private:
// Constructor
iter_impl(std::list<Edge>::const_iterator start) : current(start) {}

public:

Edge operator*() {
return *current;
}

Graph::iter_impl& operator++() {
++current;
return *this;
}

bool operator==(const Graph::iter_impl& other) const {


const iter_impl* ptr_other =
dynamic_cast<const iter_impl*>(&other);
if (ptr_other == NULL) return false;
return current == ptr_other->current;
}

Graph::iter_impl* clone() {
return new iter_impl(current);
}
GIT – Computer Engineering Department 39
The List_Graph::iter_impl class (2)
private:
// Data fields

/** Iterator to the list of edges */


std::list<Edge>::const_iterator current;
friend class List_Graph;

}; // End iter_impl

GIT – Computer Engineering Department 40


Performance
 Two implementations
– Adjacency list
– Adjacency matrix
 Which one is better?
– In terms of storage
– In terms of time

GIT – Computer Engineering Department 41


Performance
 Performance in terms of storage
– Space requirement = θ(|V|2) in adjacency matrix
– Space requirement = O(|E|+|V|) in adjacency list

– Which one is better for sparse graphs?


– What about the constant hidden in asymptotic
notation?

GIT – Computer Engineering Department 42


Performance
 Performance in terms of time
– Depends on the algorithm
– Ex: consider the following code

for each vertex u in the graph


for each vertex v adjacent to u
do something with edge (u,v)

GIT – Computer Engineering Department 43


Performance
 For adjacency list
– An iteration over all vertices adjacent to a given
vertex is O(|Ev|)
– An algorithm that iterates over all of the edges by
iterating over the vertices is O(|E|)
 For adjacency matrix
– Need to go over all vertices for each vertex u
– θ(|V|2)

GIT – Computer Engineering Department 44


Performance
– Ex: consider the following code

for each vertex u in some subset of the vertices


for each vertex v in some subset of the vertices
if (u,v) is an edge
do something with the edge

GIT – Computer Engineering Department 45


Observation About Adjacency List Representation

 For adjacency list


– The operation
is_edge(int u, int v)
is O(|Ev|) where |Ev| is the number of edges
originating from v
– The total run time is O(|V| |E| )
 For adjacency matrix
– Same operation is done in constant time
– The total run time is O(|V|2)

GIT – Computer Engineering Department 46


Which to Use?
 Generally |E| < < |V|2
– i.e. the adjacency matrix is sparse.
 Thus, for most applications, the adjacency list
is preferred.
 There are some algorithms, however, where
the adjacency matrix is preferred.

GIT – Computer Engineering Department 47


Breadth First Search
 Starting at a source vertex
 Systematically explore the edges to “discover”
every vertex reachable from s.
 Produces a “breadth-first tree”
– Root of s
– Contains all vertices reachable from s
– Path from s to v is the shortest path

GIT – Computer Engineering Department 48


Algorithm
1. Take a start vertex, mark it identified (color it gray),
and place it into a queue.
2. While the queue is not empty
1. Take a vertex, u, out of the queue (Begin visiting u)
2. For all vertices v, adjacent to u,
1. If v has not been identified or visited
1. Mark it identified (color it gray)
2. Place it into the queue
3. Add edge u, v to the Breadth First Search Tree
3. We are now done visiting u (color it black)

GIT – Computer Engineering Department 49


Example

0 4

3 1 6

2 7

9 8

GIT – Computer Engineering Department 50


Example

GIT – Computer Engineering Department 51


Trace of Breadth First Search

Vertex Being Visited Queue Contents after Visit Visit Sequence


0 13 0
1 32467 01
3 2467 013
2 46789 0132
4 67895 01324
6 7895 013246
7 895 0132467
8 95 01324678
9 5 013246789
5 empty 0132467895

GIT – Computer Engineering Department 52


Breadth-First Search Tree

vector<int> parent

[0] -1
[1] 0
[2] 1
[3] 0
[4] 1
[5] 4
[6] 1
[7] 1
[8] 2
[9] 2

GIT – Computer Engineering Department 53


Application of BFS
 A Breadth First Search finds the shortest path
from the start vertex to all other vertices
based on number of edges.
 We can use a Breadth First Search to find the
shortest path through a maze.
 This may be a more efficient solution than that
found by a backtracking algorithm.

GIT – Computer Engineering Department 54


Recursive Solution to a Maze

GIT – Computer Engineering Department 55


Maze as a Graph
0
1 2

3
8
4 5 6 7

11
10

12

GIT – Computer Engineering Department 56


Breadth First Search Tree
0

2 4

8 7 5

12 11 6 9 3 10

GIT – Computer Engineering Department 57


Maze Solution
0
1 2

3
8
4 5 6 7

11
10

12

GIT – Computer Engineering Department 58


Implementing Breadth First Search
 The breadth_first_search function will
create the Breadth First Search tree by
returning a vector that gives the parent of
each vertex in the tree.
 Generally we are interested in the path from
the starting vertex to a given target vertex.
– Using this array we can construct this path by
entering the vertices into a stack and reversing
their order.

GIT – Computer Engineering Department 59


Code for Breadth First Search
vector<int> breadth_first_search(const Graph& graph, int start) {
int num_v = graph.get_num_v();
queue<int> the_queue;
vector<int> parent(num_v, -1);
vector<bool> identified(num_v, false);
identified[start] = true;
the_queue.push(start);
/* While the queue is not empty */
while (!the_queue.empty()) {
/* Take a vertex, current, out of the queue
(Begin visiting current).*/
int current = the_queue.front();
the_queue.pop();

GIT – Computer Engineering Department 60


Code for Breadth First Search (2)
/* For all vertices, neighbor, adjacent to current */
Graph::iterator itr = graph.begin(current);
while (itr != graph.end(current)) {
Edge edge = *itr;
int neighbor = edge.get_dest();
/* If neighbor has not been identified */
if (!identified[neighbor]) {
/* Mark it identified */
identified[neighbor] = true;
/* Place it into the queue */
the_queue.push(neighbor);
/* Insert the edge (current, neighbor)
into the tree */
parent[neighbor] = current;
}
++itr;
}
// Finished visiting current.
}
return parent;

GIT – Computer Engineering Department 61


Depth First Search
 Start at some vertex
 Follow a simple path discovering new vertices
until you cannot find a new vertex.
 Back-up until you can start finding new
vertices.

GIT – Computer Engineering Department 62


Algorithm for DFS
1. Start at vertex u. Mark it visited (color gray) and
set its discovery time.
2. For each vertex v adjacent to u
1. If v has not been visited
1. Insert u, v into DFS tree
2. Recursively apply this algorithm starting at v
3. Mark u finished (color it black) and set its finish
time.
 Note: for a Directed graph, a DFS may produce
multiple trees – this is called a DFS forest

GIT – Computer Engineering Department 63


DFS Example
0

1 2

3 4 5 6

GIT – Computer Engineering Department 64


DFS Example

GIT – Computer Engineering Department 65


Trace of Depth-First Search

Operation Adjacent Vertices Discovery Order Finish Order


Visit 0 1234 0
Visit 1 034 01
Visit 3 014 013
Visit 4 013 0134
Finish 4 4
Finish 3 43
Finish 1 431
Visit 2 056 01342
Visit 5 26 013425
Visit 6 25 0134256
Finish 6 4316
Finish 5 53165
Finish 2 531652
Finish 0 5316520

GIT – Computer Engineering Department 66


Depth-First Search Tree

GIT – Computer Engineering Department 67


Depth First Search Starter Function
void depth_first_search(const Graph& graph, int start,
vector<int>& parent,
vector<int>& discovery_order,
vector<int>& finish_order) {
int num_v = graph.get_num_v();
parent.clear();
parent.resize(num_v, -1);
discovery_order.clear();
discovery_order.resize(num_v, -1);
finish_order.clear();
finish_order.resize(num_v, -1);
vector<bool> visited(num_v, false);
int discovery_index = 0;
int finish_index = 0;
for (int i = 0; i < num_v; i++) {
if (!visited[i]) {
depth_first_search(graph, i, parent,
discovery_order,
finish_order,
visited,
discovery_index,
finish_index);
}
}
}

GIT – Computer Engineering Department 68


Depth_First_Search Recursive Function
void depth_first_search(const Graph& graph, int current,
vector<int>& parent,
vector<int>& discovery_order,
vector<int>& finish_order,
vector<bool>& visited,
int& discovery_index,
int& finish_index) {
visited[current] = true;
discovery_order[discovery_index++] = current;
/* For each vertex adjacent to the current vertex. */
for (Graph::iterator itr = graph.begin(current);
itr != graph.end(current); ++itr) {
int neighbor = (*itr).get_dest();
// if neighbor has not been visited
if (!visited[neighbor]) {
/* Insert (current, neighbor) into the depth- first search tree */
parent[neighbor] = current;
// Recursively apply the algorithm starting at neighbor.
depth_first_search(graph, neighbor,
parent, discovery_order,
finish_order, visited,
discovery_index, finish_index);
}
}
// Mark current finished
finish_order[finish_index++] = current; }

GIT – Computer Engineering Department 69


Application of DFS
 A topological sort is an ordering of the
vertices such that if (u, v) is an edge in the
graph, then v does not appear before u in the
ordering.
 A Depth First Search can be used to
determine a topological sort of a Directed
Acyclic Graph (DAG)
 An application of this would be to determine
an ordering of courses that is consistent with
the prerequisite requirements
GIT – Computer Engineering Department 70
CIS Prerequisites

GIT – Computer Engineering Department 71


Topological Sort Algorithm
 Observation: If there is an edge from u to v,
then in a DFS u will have a finish time later
than v.
 Perform a DFS and record the finish times.
 Order the vertices by decreasing finish time.

GIT – Computer Engineering Department 72


Shortest Path Problem
 Shortest Path Problem :
Given as input a graph, G=(V,E), find the shortest
path from vertex v to vertex w in G

 Input is a weighted graph : associated with each edge (vi ,vj)


is a cost ci,j to traverse the edge.
 Cost of a path v1 v2 … vN (weighted path lenght ) is
N −1

∑c
i =1
i ,i +1

 Remember, unweighted path lenght is merely the number


of edges on the path, N-1

GIT – Computer Engineering Department 73


Example - Directed Weighted Graph

1
100
10

2 5

30
50

10

60
20
3 4

GIT – Computer Engineering Department 74


Another Weighted Graph

GIT – Computer Engineering Department 75


Shortest Path Problem
 Negative edges can cause problems!
 Path from v5 to v4 has cost 1 but a shorter path exists by
following the loop v5, v4, v2, v5, v4, has a cost -5
 Shortest path is undefined if there is a negative cost
cycle

GIT – Computer Engineering Department 76


Shortest Path Problem
Currently there are no algorithms in which finding
the path from s to one vertex is any faster (by more
than a constant factor) than finding the paths from s
to all other vertices

GIT – Computer Engineering Department 77


Finding the Shortest Paths
Single Source Shortest Paths Problem :
Given as input
– a graph, G=(V,E) and
– a distinguished vertex, s
Find
– the shortest paths from s to every other
vertex in G

GIT – Computer Engineering Department 78


Finding the Shortest Paths
 The famous computer scientist Edsger W.
Dijkstra developed an algorithm to solve this
problem.
 This algorithm is an example of a greedy
algorithm.
– A greedy algorithm is one that attempts to find the
locally optimal solution at each step

GIT – Computer Engineering Department 79


Dijkstra’s Algorithm
 A tentative distance dv is kept for each vertex
 This distance turns out to be the shortest path length
from s to v using only known vertices as
intermediates
 We record pv, which is the last vertex to cause a
change to dv
 Dijkstra’s algorithm proceeds in stages
 At each stage
– select a vertex v, which has the smallest dv among all the
unknown vertices
– declare that shortest path from s to v is known
– update the values of dw for each vertex w adjacent to v

GIT – Computer Engineering Department 80


Dijkstra’s Algorithm
1. Initialize S with the start vertex, s, and V–S with the remaining vertices.
2. for all v in V – S
3. Set p[v] to s
4. if there is an edge (s, v)
5. Set d[v] to w(s, v)
else
6. Set d[v] to ∞
7. while V – S is not empty
8. for all u in V – S, find the smallest d[u]
9. Remove u from V – S and add it to S
10. for all v adjacent to u in V – S
11. if d[u] + w(u, v) is < d[v]
12. Set d[v] to d[u] + w(u, v)
13. Set p[v] to u.

GIT – Computer Engineering Department 81


Dijkstra’s Algorithm

Example :
 Assume that start node s is v1
 First vertex selected is v1  Initial configuration of
– with path length 0 vectors in Dijkstra’s
 This vertex is marked known Algorithm

GIT – Computer Engineering Department 82


Stages of Dijkstra’s Algorithm

GIT – Computer Engineering Department 83


Stages of Dijkstra’s Algorithm

GIT – Computer Engineering Department 84


Stages of Dijkstra’s Algorithm

GIT – Computer Engineering Department 85


Stages of Dijkstra’s Algorithm

GIT – Computer Engineering Department 86


Stages of Dijkstra’s Algorithm

GIT – Computer Engineering Department 87


Stages of Dijkstra’s Algorithm

GIT – Computer Engineering Department 88


Analysis of Dijkstra’s Algorithm
 Step 1 requires |V| steps.
 The loop at Step 2 will be executed |V| – 1 times
 The loop at Step 7 will be executed |V| – 1 times
 Within the loop at Step 7
– Steps 8 and 9 will search |V – S| items
– Thus Step 7 is |V| -1 + |V| - 2 + … 1 = O(|V|2)

GIT – Computer Engineering Department 89


Improving Implementation of Dijkstra’s Algorithm

 We use a tripple to contain d[u], u, p[u] and use d[u]


as the key for comparison.
 We can then place these triples into a priority queue
and adapt the breadth-first-search algorithm.

GIT – Computer Engineering Department 90


Improved Dijkstra’s Algorithm
1. Take the start vertex and place the triple (0, s, -1) into the priority queue.
2. While the priority queue is not empty
3. Take the triple with the smallest d[u] out of the queue.
4. If u has not been visited
5. Mark it visited and place (p[u], u) into the result.
6. For all vertices, v, adjacent to u
7. Compute d[v] = d[u] + w(u, v) and
place (d[v], v, u) into the priority queue.

GIT – Computer Engineering Department 91


Analysis of revised algorithm
 Assume that all edges get entered into the priority
queue.
 Thus the while loop is executed |E| times.
 If we use a heap for the priority queue, each insert
and removal is log |E|.
 Thus we have O(|E| log |E|).

GIT – Computer Engineering Department 92


Minimum Spanning Tree
 Let G = (V, E) be an un-directed weighted graph.
 Wish to find an acyclic subset T ⊆ E such that
w(T) = ∑(u,v) ∈T w(u,v)
is the minimum.
 This is the minimum spanning tree.
 A minimum spanning tree of an undirected graph G
is a tree formed from graph edges that connects all
the vertices of G at lowest total cost
 A minimum spanning tree exists iff G is connected

GIT – Computer Engineering Department 93


Minimum Spanning Tree
Second graph is the
minimum spanning tree
of first

Number of edges in
minimum spanning tree
is |V| -1

Minimum spanning tree


is a tree because it is
acyclic and connected;
it is spanning because it
covers every vertex

GIT – Computer Engineering Department 94


Prim’s Algorithm
 One way to compute a minimum spanning tree is to
grow the tree in successive stages.
 In each stage
– one node is picked as the root
– we add an edge and thus an associated vertex to the tree
 At any point of the algorithm, we have a set of
vertices that have already been included in the tree
 The algorithm then finds, at each stage, a new
vertex to add to the tree by choosing the edge (u,v)
– Cost of (u,v) is the smallest among all edges where u is in
tree and v is not

GIT – Computer Engineering Department 95


Prim’s Algorithm

GIT – Computer Engineering Department 96


Prim’s Algorithm
 Prim’s algorithm is identical to Dijkstra’s
algorithm for shortest path
 We keep values
– dv  weight of shortest edge connecting v to a
known vertex
– pv  last vertex to cause a change in dv

GIT – Computer Engineering Department 97


Prim’s Algorithm
1. Initialize S with the start vertex, s, and V–S with the remaining vertices
2. for all v in V – S
3. if there is an edge (s, v)
4. Set d[v] to w(s, v)
5. Set p[v] to s
else
6. Set d[v] to ∞
7. Set p[v] to NULL
8. while V – S is not empty
9. for all u in V – S, find the smallest d[u]
10. Remove u from V – S and add it to S
11. Insert the edge (u, p[u]) into the spanning tree.
12. for all v adjacent to u in V – S
13. if w(u, v) < d[v]
14. Set d[v] to w(u, v)
15. Set p[v] to u.

GIT – Computer Engineering Department 98


Example

GIT – Computer Engineering Department 99


Building the MST

GIT – Computer Engineering Department 100


Analysis of Prim’s Algorithm
 The outer loop is executed n-1 times, each
time adding an edge
 There are two inner loops:
– one to find the minimum item in the remaining list,
– and the other to update the distances from nodes
inside the set S to nodes outside the set S.

GIT – Computer Engineering Department 101


Analysis of Prim’s Algorithm
 These loops also run |V| times.
– Thus the implementation is O(|V|2) assuming that the
adjacency matrix representation of the graph is used.
 If we could improve upon the find minimum and
update distance operations to say log |V|, this could
be improved to O(|E|log|V|).
 Computer science researchers have developed
advanced priority queue implementations that give
O(|E| + |V| log |V|) or better performance

GIT – Computer Engineering Department 102

You might also like