Sei sulla pagina 1di 134

Graph Algorithms

Chapter 9

Fall 2015 2015 by Greg Ozbirn, UT-Dallas, for use with 1


Data Structures book by Mark Allen Weiss
Definitions
A graph G = (V,E) consists of vertices, V, and
edges, E.
Each edge is a pair (v,w) where v and w are in V.
If the edge has direction then the graph is a
directed graph, or digraph.
Two vertices are adjacent if there is an edge
between them (or an edge in the direction for a
directed graph).
An edge can also have a value representing weight
or cost.
2
Undirected Graph

Vertices

Adjacent Vertices

Edge

3
Directed Graph (also called Digraph)

Edges have direction 4


Definitions
A path is a sequence of vertices connected by edges.
The length of the path is the number of edges (N-1).
A vertex can have a path to itself, either of length
zero with no edges, or else a loop of one edge.
A simple path has distinct vertices, except the first
and last vertex could be the same.

5
Definitions
A cycle is a path of length >= 1 starting and
ending at the same vertex.
In a directed graph, a path of u-v-u would be a
cycle, since the (u,v) edge is different from the
(v,u) edge.
In an undirected graph, the edges of a cycle must
be distinct, so u-v-u is not a cycle.
A graph without cycles is called acyclic.
A directed acyclic graph is abbreviated DAG.
6
Path (shown in blue)

Length is 3 because there are 3 (N-1) edges in the path


7
Loop is an edge from a vertex to itself.

Loop

8
Cycle in a directed graph

9
Cycle in an undirected graph

10
Directed Acyclic Graph (DAG)

11
Definitions
A graph is connected if there is a path from
every vertex to every other vertex.
A directed graph with paths between all
vertices is said to be strongly connected.
A directed graph is weakly connected if its
undirected representation is connected.
A complete graph has edges between every
pair of vertices.
12
A Connected Graph

13
Graph that is not connected

14
A Weakly Connected Graph

Underlying undirected graph is connected 15


A Strongly Connected Graph

Every vertex reachable from every other vertex 16


A Complete Graph

Every vertex connects to every other vertex 17


Examples
An airport system can be modeled as a
graph.
Each airport can be a vertex.
Edges can represent non-stop flights.
Edges could have weights representing the
distance or cost of the flight.

18
An Airport System

HOU
ATL

DFW

AUS
BNA

SHV

19
An Airport System

HOU
ATL
1 2
1
DFW
.75

AUS 1 BNA

SHV

Weights could represent flight duration 20


Examples
Traffic flow can be modeled as a graph.
Each street intersection can be a vertex, and
each street an edge.
Edges could have values representing
capacity or speed limits.

21
A Traffic Flow System

1.3 1.8
Campbell Campbell Campbell
/Coit /Floyd /75

1.1

Coit/
Arapaho

Weights could represent distance between intersections 22


Representation of Graphs
A simple choice is a 2D array.
This is called an Adjacency Matrix.
Space requirement is (|V|2), where |V| denotes
the number of vertices.
If the graph is dense, |E| = (|V|2), this is okay.
If the graph is sparse, so that there are few edges
compared to the number of possible edges, it is a
poor use of space.

23
Adjacency Matrix

ATL AUS DFW HOU SHV BNA

ATL 0 0 1 0 0 1
AUS 0 0 1 0 0 0
DFW 1 1 0 1 1 0
HOU 0 0 1 0 0 0
SHV 0 0 1 0 0 0
BNA 1 0 0 0 0 0

Sparse matrix, mostly zeroes. Space required is (|V|)2. 24


Adjacency List
For a sparse graph (|E| << |V|2), an
adjacency list is a better solution.
For each vertex, we keep a list of all
adjacent vertices.
The space required is O(|E| + |V|) which is
linear in the size of the graph.

25
ATL DFW BNA
AUS DFW
DFW ATL AUS HOU SHV
HOU DFW
SHV DFW
BNA ATL

Adjacency list
26
Topological Sort
A topological sort is an ordering of vertices
in a directed acyclic graph such that if there
is a path from vi to vj, then vj appears after
vi in the ordering.
It is not a unique ordering.
Informally, a topological sort is a list of the
vertices of a DAG in which all the
successors of any given vertex appear in the
sequence after that vertex.
27
Topological Sort
An example would be courses and their
prerequisites.
Any ordering that does not violate the
prerequisite requirement would be a
topological sort.

28
Topological Sort
Example d

b g

a e i

c h

Other possibilites:
f S = {a,b,c,f,e,d,h,g,i}
S = {a,b,d,e,g,c,f,h,i}
S = a,b,c,d,e,f,g,h,i S = {a,c,f,b,d,e,h,g,i}
29
Algorithm to Produce a Topological Sort

Repeat the following steps until the graph is


empty:
1. Select a vertex that has indegree zero.
2. Add the vertex to the sort.
3. Delete the vertex and all the edges
emanating from it from the graph.

Indegree zero means no incoming edges.


30
//Pseudocode for topological sort:
void topsort( ) throws CycleFoundException
{
Vertex v, w;
for (int counter = 0;
counter < NUM_VERTICES; counter++)
{
v = findNewVertexOfDegreeZero( );
if (v == null) // none found
throw new CycleFoundException( );
v.topNum = counter; // give it a topolog. num
for each w adjacent to v
w.indegree--; // reduce indegree of adj. vs
}
} 31
Topological Sort
The running time of the algorithm is O(|V| 2) since
each call to find the indegree zero vertex is a
linear scan of all of V, and there are |V| calls.
The running time can be improved by keeping the
indegree zero vertices separate after we identify
them. This yields a running time of O(|E| + |V|).
Since we identify them as we reduce indegree of
adjacent vertices, we can simply put them into a
queue at that time, avoiding the linear scan.
32
void topsort( ) throws CycleFoundException
{
Queue<Vertex> q = new Queue<Vertex>();
int counter=0;
for each Vertex v
if (v.indegree == 0)
q.enqueue(v); // enqueue indegree zero vertices
while (!q.isEmpty() )
{
Vertex v = q.dequeue();
v.topNum = ++counter; // give it a topolog. num
for each Vertex w adjacent to v
if ( --w.indegree == 0)
q.enqueue(w); // enqueue newly identified indegree zero
} // vertices
if (counter != NUM_VERTICES)
throw new CycleFoundException( );
33
}
void topsort( ) throws CycleFoundException
{
Queue<Vertex> q = new Queue<Vertex>();
int counter=0;
for each Vertex v
if (v.indegree == 0)
q.enqueue(v); // enqueue indegree zero vertices
O(|V|) dequeues
while (!q.isEmpty() )
{
Vertex v = q.dequeue();
v.topNum = ++counter; // give it a topolog. num
for each Vertex w adjacent to v O(|E|) compares
if ( --w.indegree == 0)
q.enqueue(w); // enqueue newly identified indegree zero
} // vertices
if (counter != NUM_VERTICES)
throw new CycleFoundException( );
34
}
Shortest-Path Algorithms
Two kinds of path lengths:
Weighted path length: the sum of the
weights on the path.
Unweighted path length: the number of
edges in the path, N-1.

35
Shortest-Path Algorithms
Single-source shortest path problem: find
the shortest weighted path from a vertex, s,
to every other vertex in the graph.

36
2
v1 v2
10
4 1 3
2 2
v3 v4 v5
8 4
5 6
v6 v7
1

Shortest weighted path from v1 to v6 is 6.


Shortest unweighted path from v1 to v6 is 2.
37
Examples
If the vertices represent computers, the
edges could represent links between them,
with values as the communication costs.
The shortest path is then the cheapest route.
If the vertices represent airplane or other
traffic routes, the shortest path represents
the best route between two points.

38
Unweighted Shortest Paths
An unweighted shortest path problem can
be solved by treating all edges as having
weight = 1.
Therefore, it can be solved as a special case
of the weighted shortest path problem.

39
Unweighted Shortest Paths
We can determine distances from a vertex by
starting with the vertex and finding all
adjacent vertices. These have length 1.
Then we move to each of the adjacent
vertices and find all of their adjacent vertices
not already visited. These have length 2.
We continue until all vertices are visited.
This is called a breadth-first search.
40
1 2

v1 v2
2

v3 v4 v5
0 3
v6 v7

1 3

Breadth-first search from v3.


Start at v3.
41
1 2

v1 v2
2

v3 v4 v5
0 3
v6 v7

1 3

Breadth-first search from v3.


Visit adjacent vertices v1 and v6. (Length = 1)
42
1 2

v1 v2
2

v3 v4 v5
0 3
v6 v7

1 3

Breadth-first search from v3.


Visit adjacent vertices v2 and v4. (Length = 2)
43
1 2

v1 v2
2

v3 v4 v5
0 3
v6 v7

1 3

Breadth-first search from v3.


Visit adjacent vertices v5 and v7. (Length = 3)
44
Unweighted Shortest Paths
In order to write code for this, we can use a
table to keep track of each vertex as it is
visited.
This is shown on the following slide:

45
Computing unweighted shortest path from v3 to all other vertices.

V known dv pv
---------------------------------------
v1 F 0
v2 F 0
v3 F 0 0
v4 F 0
v5 F 0
v6 F 0
v7 F 0

known is set to true after a vertex is processed.


dv is distance from v3.
Start all vertices at infinite distance except v3 which is 0.
pv is the previous vertex used to reach this vertex.
46
Computing unweighted shortest path from v3 to all other vertices.

V known dv pv
---------------------------------------
v1 F 1 v3
v2 F 0
v1 v2
v3 T 0 0
v4 F 0 v3 v4 v5
v5 F 0 v6 v7
v6 F 1 v3
v7 F 0

v3 is known.
Find v1 and v6 at distance 1 (from v3).

47
Computing unweighted shortest path from v3 to all other vertices.

V known dv pv
---------------------------------------
v1 T 1 v3
v2 F 2 v1
v1 v2
v3 T 0 0
v4 F 2 v1 v3 v4 v5
v5 F 0 v6 v7
v6 T 1 v3
v7 F 0

v1 is known.
Find v2 and v4 at distance 2.
pv is v1 because that is how we reached v2 and v4.
v6 is known, has no successors.
48
Computing unweighted shortest path from v3 to all other vertices.

V known dv pv
---------------------------------------
v1 T 1 v3
v2 T 2 v1
v1 v2
v3 T 0 0
v4 T 2 v1 v3 v4 v5
v5 F 3 v2 v6 v7
v6 T 1 v3
v7 F 3 v4

v2 is known.
Find v5 at distance 3.
pv is v2 for v5 because that is how we reached v5.
v4 is known.
Find v7 at distance 3.
49
pv is v4 for v7 because that is how we reached v7.
Computing unweighted shortest path from v3 to all other vertices.

V known dv pv
---------------------------------------
v1 T 1 v3
v2 T 2 v1
v1 v2
v3 T 0 0
v4 T 2 v1 v3 v4 v5
v5 T 3 v2 v6 v7
v6 T 1 v3
v7 T 3 v4

v5 is known and has no unknown successors. Same for v7.


All vertices are now known, algorithm is done.
dv gives distance to each vertex.
To find the path from v3 to v7:
trace pv from v7:
50
v7 -> v4 -> v1 -> v3, so path is v3, v1, v4, v7
Pseudocode for unweighted shortest-path problem.
void unweighted( Vertex s )
{
for each Vertex v
{
v.dist = INFINITY; v.known = false;
}

s.dist = 0; // start source vertex at distance zero


for (int currDist = 0; currDist < NUM_VERTICES; currDist++ )
for each Vertex v
if ( !v.known && v.dist == currDist )
{ v1 v2
v.known = true;
for each Vertex w adjacent to v v3 v4 v5
if (w.dist == INFINITY) v6 v7
{
w.dist = currDist + 1;
w.path = v;
}
} 51
} // can be made more efficient by enqueueing the ws as next vs.
Pseudocode for unweighted shortest-path problem.
void unweighted( Vertex s )
{ O(|V|)
for each Vertex v
{
v.dist = INFINITY; v.known = false;
} O(|V|)
s.dist = 0; // start source vertex at distance zero
for (int currDist = 0; currDist < NUM_VERTICES; currDist++ )
for each Vertex v O(|V|)
if ( !v.known && v.dist == currDist )
{
v.known = true;
for each Vertex w adjacent to v
if (w.dist == INFINITY) O(|E|)
{ in total
w.dist = currDist + 1;
w.path = v;
}
}
} O(|V|2 + |E|) = O(|V|2) 52
void unweighted( Vertex s ) // using queue
{
Queue <Vertex> q = new Queue<Vertex>();
for each Vertex v
v.dist = INFINITY;
s.dist = 0; // start source vertex at distance zero
q.enqueue(s); // enqueue source vertex

while ( !q.isEmpty())
{
Vertex v = q.dequeue();

for each Vertex w adjacent to v v1 v2


if (w.dist == INFINITY) v4 v5
v3
{
w.dist = v.dist + 1; v6 v7
w.path = v;
q.enqueue(w);
}
}
} 53
void unweighted( Vertex s ) // using queue
{
Queue <Vertex> q = new Queue<Vertex>();
for each Vertex v
v.dist = INFINITY;
s.dist = 0; // start source vertex at distance zero
q.enqueue(s); // enqueue source vertex
O(|V|)
while ( !q.isEmpty()) O(|E|)
{
in total
Vertex v = q.dequeue();

for each Vertex w adjacent to v v1 v2


if (w.dist == INFINITY) v4 v5
v3
{
w.dist = v.dist + 1; v6 v7
w.path = v;
q.enqueue(w);
}
}
} O(|E| + |V|) 54
Dijkstras Algorithm
Dijkstras algorithm solves the general
(weighted) single-source shortest-path
problem.
It is a greedy algorithm.
A greedy algorithm works in stages, and
does what appears to be the best thing at
each stage.

55
Dijkstras Algorithm
The algorithm proceeds in stages.
At each stage, it selects a vertex which has
the smallest distance among all the
unknown vertices.
It then declares this vertex known, updates
the table for the adjacent vertices if the cost
is less than the current cost, and repeats this
again for the next least distance vertex, until
all vertices are known.
56
v1 v2
2
10
4 1 3
2 2
v3 v4 v5
8 4
5 6
v6 v7
1
V known dv pv Find shortest path from v1
--------------------------------------- to all other vertices.
v1 F 0 0
v2 F 0 Start with v1 at distance 0.
v3 F 0
v4 F 0
v5 F 0
v6 F 0
57
v7 F 0
v1 v2
2
10
4 1 3
2 2
v3 v4 v5
8 4
5 6
v6 v7
1
V known dv pv
--------------------------------------- Mark v1 as known.
v1 T 0 0 Update dv for adjacent
v2 F 2 v1 vertices v2 and v4.
v3 F 0 Choose v4 since it has the
v4 F 1 v1 least dv among all
v5 F 0 unknown vertices.
v6 F 0
58
v7 F 0
v1 v2
2
10
4 1 3
2 2
v3 v4 v5
8 4
5 6
v6 v7
1

V known dv pv
--------------------------------------- Mark v4 as known.
v1 T 0 0 Update dv for adjacent
v2 F 2 v1 vertices v3, v5, v6, v7.
v3 F 3 v4 Choose v2 next since
v4 T 1 v1 it has least dv among
v5 F 3 v4 all unknown vertices.
v6 F 9 v4
59
v7 F 5 v4
v1 v2
2
10
4 1 3
2 2
v3 v4 v5
8 4
5 6
v6 v7
1
V known dv pv
--------------------------------------- Mark v2 as known.
v1 T 0 0 Adjacent vertices:
v2 T 2 v1 v4 is already known.
v3 F 3 v4 v5 has cost 12 from v2
v4 T 1 v1 which is not better than
v5 F 3 v4 what we already have.
v6 F 9 v4 Choose v3 or v5 next,
v7 F 5 v4 we will choose v3. 60
v1 v2
2
10
4 1 3
2 2
v3 v4 v5
8 4
5 6
v6 v7
1
V known dv pv
--------------------------------------- Mark v3 as known.
v1 T 0 0 Adjacent vertices:
v2 T 2 v1 v1 already known.
v3 T 3 v4 v6 updated to 8.
v4 T 1 v1 Choose v5 next.
v5 F 3 v4
v6 F 8 v3
61
v7 F 5 v4
v1 v2
2
10
4 1 3
2 2
v3 v4 v5
8 4
5 6
v6 v7
1
V known dv pv
--------------------------------------- Mark v5 as known.
v1 T 0 0 Adjacent vertices:
v2 T 2 v1 v7 not improved.
v3 T 3 v4 Choose v7 next.
v4 T 1 v1
v5 T 3 v4
v6 F 8 v3
62
v7 F 5 v4
v1 v2
2
10
4 1 3
2 2
v3 v4 v5
8 4
5 6
v6 v7
1
V known dv pv
--------------------------------------- Mark v7 as known.
v1 T 0 0 Adjacent vertices:
v2 T 2 v1 v6 improved to 6.
v3 T 3 v4 Choose v6 next.
v4 T 1 v1
v5 T 3 v4
v6 F 6 v7
63
v7 T 5 v4
v1 v2
2
10
4 1 3
2 2
v3 v4 v5
8 4
5 6
v6 v7
1
V known dv pv
--------------------------------------- Mark v6 as known.
v1 T 0 0 Adjacent vertices:
v2 T 2 v1 None.
v3 T 3 v4 Done.
v4 T 1 v1
v5 T 3 v4 Distances in dv.
v6 T 6 v7 Path given by pv.
64
v7 T 5 v4
void dijkstra( Vertex s )
{
for each Vertex v
{ v.dist = INFINITY; v.known = false; }
s.dist = 0; // start source vertex at distance zero
for (; ;) {
Vertex v = smallest unknown distance vertex
if ( v == null)
break;
v.known = true;
for each Vertex w adjacent to v
if (!w.known)
if (v.dist + cvw < w.dist) // cvw is cost from v to w
{ // update w
decrease (w.dist to v.dist + cvw);
w.path = v;
}
}
} 65
}
void dijkstra( Vertex s )
{ O(|V|)
for each Vertex v
{ v.dist = INFINITY; v.known = false; }
s.dist = 0; // start source vertex at distance zero
for (; ;) { O(|V|)
Vertex v = smallest unknown distance vertex
if ( v == null) O(|V|) or
break; O(log|V|)
v.known = true; using heap
for each Vertex w adjacent to v
if (!w.known) O(|E|) in total
if (v.dist + cvw < w.dist) // cvw is cost from v to w
{ // update w
decrease (w.dist to v.dist + cvw);
w.path = v;
} O(log|V|) using heap
}
} 66
}
Dijkstra
If a linear scan of the vertices is used to find the
vertex of least cost, this step takes O(|V|).
Since the loop processes each vertex for O(|V|)
time, then O(|V|2) time is required.
The inner update loop takes O(|E|) since the
update is constant time.
So, the running time is O(|E| + |V| 2).
If the graph is dense so that |E| = (|V|2), then the
algorithm is linear in the number of edges.
67
Dijkstra
If the graph is sparse, with |E| = (|V|), then the algorithm
is too slow.
It can be improved by using a priority queue for getting the
next cheapest cost vertex.
Removing each vertex is O(log|V|).
The edge updates require a O(log|V|) decreaseKey for
each edge over the course of the algorithm.
So, the running time is:
find next min edge updates
O(|V| log |V| + |E| log|V|)= O(|E| log|V|)
68
Negative Edges
Dijkstras algorithm will not work if there
are negative edges.
When a vertex is declared known, we have
taken an edge that was the cheapest,
assuming any other path would be more
costly. But this might not be so if some
edge had a negative cost.

69
v1 v2
5
4 -3
v3

In the above graph, Dijkstras would choose the v1-v3


edge next at cost 4, when actually the other path is
cheaper if a negative edge is allowed.

Graphs with negative edge costs can be solved with a


modification to Dijkstras algorithm, but the running
time is worse.

70
Acyclic Graphs
If a graph is acyclic, Dijkstras algorithm
can be improved by choosing vertices in
topological order.
When a vertex is selected, its distance
cannot be lowered since there are no
incoming edges from unknown vertices.

71
Network Flow Problems
Edges of a graph can represent capacity.
In such a graph we might want to know the
maximum flow between two vertices, which
we will refer to as the source and sink.
Such problems occur in any kind of network
involving flow, such as water through pipes
or cars through streets.

72
Cuts
Consider the flow from source s to sink t.
6 units may leave s, and 6 units may enter t.
But all flow must pass through the cut,
which restricts the flow to 5.
4 s 2
Max flow = min cut. 1
a b
2 2
4
c d
3 3
t 73
Maximum Flow Algorithm
The algorithm proceeds in stages.
We first construct a flow graph, Gf.
Initially all edges show no flow.
We then construct another graph called the
residual graph, Gr, which is the difference
between the original graph and the flow graph.
Gr tells how much more flow an edge can handle.

74
Algorithm
At each stage, we find a path in Gr from s to t
called the augmenting path.
The minimum edge on this path is the amount of
flow that may be added to every edge on the path.
We then adjust Gf by this flow and reduce Gr.
When all paths have been processed, we are done.

75
Gf Gr
4 s 2 0 s 0 4 s 2
1 0 1
a b a b a b
2 2 0 0 2 2
4 0 4
c d c d c d
3 3 0 0 3 3
t t t

Start with the flow graph, Gf all 0, and the residual graph, Gr = G.

76
Gf Gr
0 s 0 4 s 2
0 1
a b a b
0 0 2 2
0 4
c d c d
0 0 3 3
t t
Choose path s,b,d,t giving a flow of 2 through this path.

Gf s Gr s
0 2 4 0
0 1
a b a b
0 2 2 0
0 4
c d c d
0 2 3 1
t t
Add this flow to Gf, remove from Gr. 77
Gf Gr
0 s 2 4 s 0
0 1
a b a b
0 2 2 0
0 4
c d c d
0 2 3 1
t t
Choose path s,a,c,t giving a flow of 2 through this path.

Gf s Gr s
2 2 2 0
0 1
a b a b
2 2 0 0
0 4
c d c d
2 2 1 1
t t
Add this flow to Gf, remove from Gr. 78
Gf Gr
2 s 2 2 s 0
0 1
a b a b
2 2 0 0
0 4
c d c d
2 2 1 1
t t
Choose path s,a,d,t giving a flow of 1 through this path.

Gf s Gr s
3 2 1 0
0 1
a b a b
2 2 0 0
1 3
Flow of 5 reaches t, c d c d
2 from one edge, 3 from
the other. 2 3 1 0
t t
Add this flow to Gf, remove from Gr. 79
Done since no more paths from s to t. Max flow s to t is 5.
Algorithm
Unfortunately, there is a problem with this
algorithm.
It is possible that the first path chosen
results in having no other paths from s to t.
This is seen on the following slides.

80
Gf Gr
4 s 2 0 s 0 4 s 2
1 0 1
a b a b a b
2 2 0 0 2 2
4 0 4
c d c d c d
3 3 0 0 3 3
t t t
Choose path s,a,d,t.
Gf 3 s 0 Gr 1 s 2
0 1
a b a b
0 0 2 2
3 1
c d c d
0 3 3 0
t t

81
Gf Gr
4 s 2 3 s 0 1 s 2
1 0 1
a b a b a b
2 2 0 0 2 2
4 3 1
c d c d c d
3 3 0 3 3 0
t t t
Choose path s,a,c,t.
Gf 4 s 0 Gr 0 s 2
0 1
a b a b
1 0 1 2
3 1
c d c d
1 3 2 0
t t

There are no more paths from s to t and answer is short. 82


Algorithm
The solution is to keep track of removed flows
instead of deleting them.
This allows them to be put back if needed by
another path.
We can keep track of them by adding a flow in the
reverse direction to indicate we have taken flow
from this path.
If the algorithm needs the flow in a later step, it
can use this path, effectively reversing the earlier
decision.
83
Gf Gr
0 s 0 4 s 2
0 1
a b a b
0 0 2 2
0 4
c d c d
0 0 3 3
t t
Choose path s,a,d,t.
Gf Gr
3 s 0
3 s 2
1
0 1
a b a b
0 0 2 3 2
3 1
c d c d
0 3 3 0
t t 3
84
Keep track of what we used with reverse flow arrows.
Gf Gr
3 s 0
3 s 2
1 1
0
a b a b
2 3 2
0 0
3 1
c d c d
0 3 3 0
t t 3

Choose path s,b,d,a,c,t, using 2 of the 3 flow from d to a.

Gf Gr
3 s 2 3 s 2
0
1
0 1
a b a b
2 2 2 1 0
0 2
1 3
c d c d
1
2 3 2 0
t t 3
85
Done, flow is 5.
Minimum Spanning Tree
Find the set of graph edges (tree) that
connect all of the vertices at lowest cost.
This tree will be acyclic. Adding an edge
not in this tree creates a cycle.
Such a tree would be useful if, for example,
we wanted to wire a house with a minimum
amount of wire.

86
v1 v2
2
10
4 1 3
2 7
v3 v4 v5
8 4
5 6
v6 v7
1

Minimum
v1 v2
spanning tree 2
1
2
v3 v4 v5
4
6
v6 v7
1 87
Prims Algorithm
Prims algorithm grows the tree in successive
stages.
We first choose any vertex.
Then we choose the edge with least cost from this
vertex and add it to the tree.
We then choose the least edge between vertices in
the tree and those not in the tree and add it.
This is repeated until all vertices are in the tree.

88
2 2
4 1 1 3 2 10 1 1 2
3 2 4 7 5 3 2 4 5
8 4
5 6
6 7 6 7
1
2
1 2 1 1 2
3 4 5 3 2 4 5
4
6 7 6 7
2
1 1 2 1 1 2
3 2 4 5
3 4 5 4
6 7 6 7
1
2 2
1 1 2 1 1 2
3 2 4 5
3 4 5 4
6
6 7 6 7 89
1
Prims Algorithm
Prims algorithm, a greedy algorithm, is
essentially the same as Dijkstras algorithm
for shortest paths.
The main difference is the update rule.

90
v1 v2
2
10
4 1 3
2 7
v3 v4 v5
8 4
5 6
v6 v7
1
V known dv pv
---------------------------------------
v1 F 0 0
v2 F 0
v3 F 0
v4 F 0 Choose v1
v5 F 0
v6 F 0
91
v7 F 0
v1 v2
2
10
4 1 3
2 7
v3 v4 v5
8 4
5 6
v6 v7
1
V known dv pv
---------------------------------------
v1 T 0 0 Mark v1 as known.
v2 F 2 v1 Update adjacent vertices.
v3 F 4 v1 Choose v4.
v4 F 1 v1
v5 F 0
v6 F 0
92
v7 F 0
v1 v2
2
10
4 1 3
2 7
v3 v4 v5
8 4
5 6
v6 v7
1
V known dv pv
---------------------------------------
v1 T 0 0 Mark v4 as known.
v2 F 2 v1 Update adjacent vertices.
v3 F 2 v4 Choose v2 and then v3.
v4 T 1 v1
v5 F 7 v4
v6 F 8 v4
93
v7 F 4 v4
v1 v2
2
10
4 1 3
2 7
v3 v4 v5
8 4
5 6
v6 v7
1
V known dv pv
---------------------------------------
v1 T 0 0 Mark v2 and v3 as known.
v2 T 2 v1 Update adjacent vertices.
v3 T 2 v4 Choose v7.
v4 T 1 v1
v5 F 7 v4
v6 F 5 v3
94
v7 F 4 v4
v1 v2
2
10
4 1 3
2 7
v3 v4 v5
8 4
5 6
v6 v7
1
V known dv pv
---------------------------------------
v1 T 0 0 Mark v7 as known.
v2 T 2 v1 Update adjacent vertices.
v3 T 2 v4 Choose v6, and then v5.
v4 T 1 v1
v5 F 6 v7
v6 F 1 v7
95
v7 T 4 v4
v1 v2
2
10
4 1 3
2 7
v3 v4 v5
8 4
5 6
v6 v7
1
V known dv pv
---------------------------------------
v1 T 0 0 Mark v6 and v5 as known.
v2 T 2 v1 Update adjacent vertices.
v3 T 2 v4
v4 T 1 v1
v5 T 6 v7
v6 T 1 v7
96
v7 T 4 v4
v1 v2
2
1
2
v3 v4 v5
4
6
v6 v7
1
V known dv pv
---------------------------------------
v1 T 0 0 Done since all are known.
v2 T 2 v1
v3 T 2 v4 Table gives tree:
v4 T 1 v1 (v2,v1), (v3,v4), (v4,v1),
v5 T 6 v7 (v5,v7), (v6,v7), (v7, v4)
v6 T 1 v7
97
v7 T 4 v4
Prims Algorithm
Due to the similarity to Dijkstras
algorithm, the runtime analysis is the same.
The algorithm runs in O(|E| log|V|) using a
binary heap.

98
Kruskals Algorithm
A second greedy algorithm, it continually
selects the edges in order of smallest
weight, and accepts the edge if it does not
cause a cycle.

99
2 2
4 1 1 3 2 10 1 1 2
3 2 4 7 5 3 4 5
8 4
5 6
6 7 6 1
7
1
2
1 2 1 1 2
3 4 5 3 2 4 5
6 7 6 1
7
2
1 1 2 1 1 2
3 2 4 5
3 4 5 4
6 7 6 7
1
2
1 1 2 1 1 2
3 2 4 5
3 4 5 4
6
6 7 6 7 100
1 1
Kruskals Algorithm
Edge Weight Action
---------------------------------------
2
(v1,v4) 1 Accepted 4 1 1 3 2 10
(v6,v7) 1 Accepted 3 2 4 7 5
8 4
(v1,v2) 2 Accepted 5 6
(v3,v4) 2 Accepted 6 7
1
(v2,v4) 3 Rejected
(v1,v3) 4 Rejected
(v4,v7) 4 Accepted
(v3,v6) 5 Rejected
(v5,v7) 6 Accepted

101
Pseudocode for Kruskals Algorithm
public void kruskal()
{
int edgesAccepted = 0;
DisjSet ds = new DisjSet(NUM_VERTICES);
PriorityQueue<Edge> pq = new PriorityQueue<Edge>( getEdges() );
Edge e; Vertex u, v;

while (edgesAccepted < NUM_VERTICES 1)


{
e = pq.deleteMin( ); // get minimum edge = (u,v)
SetType uset = ds.find( u ); // find set vertex u is in.
SetType vset = ds.find( v ); // find set vertex v is in.
if (uset != vset) // if not same set (not yet connected)
{
// accept the edge
edgesAccepted++;
ds.union(uset, vset); // connect them
}
}
}

102
Pseudocode for Kruskals Algorithm
public void kruskal()
{
int edgesAccepted = 0;
DisjSet ds = new DisjSet(NUM_VERTICES);
PriorityQueue<Edge> pq = new PriorityQueue<Edge>( getEdges() );
Edge e; Vertex u, v;

while (edgesAccepted < NUM_VERTICES 1) O(|E|log|E|)


{
e = pq.deleteMin( ); // get minimum edge = (u,v)
SetType uset = ds.find( u ); // find set vertex u is in.
SetType vset = ds.find( v ); // find set vertex v is in.
if (uset != vset) // if not same set (not yet connected)
{
// accept the edge
edgesAccepted++;
ds.union(uset, vset); // connect them
}
}
}
O(|E|log|E|) since each edge is deleted which is log|E| time. 103
Could say O(|E|log|V|) since |E| = O(|V|2).
Depth-First Search
A depth-first search is a generalization of a preorder
traversal to apply to graphs.
Start at some vertex v, recursively traverse all
vertices adjacent to v.
When a vertex is visited, we mark it so as to avoid
problems caused by cycles in the graph.
If the graph is not connected, it will need to be
called again for each unconnected portion so that all
vertices are visited.

104
// pseudocode for depth-first search

void dfs( Vertex v)


{
v.visited = true;
for each Vertex w adjacent to v
if ( !w.visited )
dfs ( w );
}
O(|E|+|V|) since each edge and vertex are visited once. 105
Depth-First Search DFS(A)

B D E

106
Depth-First Search DFS(A)
DFS(B)
A

B D E

107
Depth-First Search DFS(A)
DFS(B)
DFS(C)
A

B D E

108
Depth-First Search DFS(A)
DFS(B)
DFS(C)
A
DFS(D)

B D E

109
Depth-First Search DFS(A)
DFS(B)
DFS(C)
A
DFS(D)
DFS(E)

B D E

110
Depth-first Spanning Tree
A depth-first search of a graph can produce
a depth-first spanning tree.
An edge to an unvisited node is called a tree
edge.
An edge to a visited node is called a back
edge.

111
Back edge
A A

Tree edge
B D E B

C
C
dfs(A)
dfs(B)
dfs(C) D E
dfs(D)
dfs(E) Tree edges are to unvisited nodes.
Back edges are to visited nodes.

Depth-first Spanning Tree 112


Depth-First Search DFS(A)

B D E

113
Depth-First Search DFS(A)
DFS(B)
A

B D E

114
Depth-First Search DFS(A)
DFS(B)
DFS(C)
A

B D E

115
Depth-First Search DFS(A)
DFS(B)
DFS(C)
A
DFS(D)

B D E

116
Depth-First Search DFS(A)
DFS(B)
DFS(C)
A
DFS(D)

B D E

117
Depth-First Search DFS(A)
DFS(B)
DFS(C)
A
DFS(D)
DFS(E)

B D E

118
Depth-First Search DFS(A)
DFS(B)
DFS(C)
A
DFS(D)
DFS(E)

B D E

119
Biconnectivity
A connected undirected graph is
biconnected if there are no vertices whose
removal disconnects the rest of the graph.

A B A

B D E C D F

G E
C
Biconnected Not biconnected 120
Biconnectivity
If a graph is not biconnected, the vertices
whose removal would disconnect the graph are
called articulation points.
These are important, for example, in a network
of computers, if the articulation node goes
down, the network is disconnected.
If a graph is biconnected, then a node going
down (a computer in a network or an
intersection of streets) still permits traffic to
flow.
121
Articulation Points
A depth-first search provides a way to find
all articulation points in a connected graph.
We can number the vertices (in preorder) as
we perform the depth first search. Num(v).
We also compute the lowest numbered
vertex reachable from each node by taking
zero or more edges followed by possibly
one back edge. Low(v).

122
Articulation Points
A root is an articulation point if it has more
than one child.
Any other vertex is an articulation point if
and only if v has some child w such that
Low(w) >= Num(v).
This means it cant reach anything above
this vertex without going through this
vertex.
123
B A

A 1/1

C D F
B 2/1

G E
C 3/1

C and D are articulation


points because they G 7/7
have a child whose low D 4/1
is greater than or equal
to their own number. Num
E 5/4
Low
F 6/4 124
Euler Circuits
Try to draw these figures without lifting the
pen off of the paper and without drawing
any line more than once:

125
Euler Circuits
Euler Path:
Find a path that visits each edge exactly
once.
Euler Circuit:
Find a cycle that begins and ends at the
same point that visits each edge exactly
once.

126
Euler Circuits
Euler circuits can be solved by constructing
a graph where there is a vertex at each
intersection in the figure and an edge for
each line.

127
5 6

7
8 9
4 10
3 2
1

Any connected graph, all of whose vertices


have even degree, must have an Euler circuit.
If the graph has no more than two vertices with
odd degree, it has an Euler path.

128
Euler Circuits
Euler circuits can be found using a series of depth-
first searches.
If the search returns to a node with no untraversed
edges, the algorithm picks the first vertex on the
path that has an untraversed edge and performs a
depth-first search again from that vertex, splicing
its list of traversed vertices into the first traversal.
This continues until all edges are visited.
The resulting set of vertices is an Euler circuit.

129
C A

D B

DFS(A)

C A

D B

Path: A, C, D, A, stuck at A 130


C is first vertex on path having untraversed edges
DFS(C)
C A

D B

C A

D B

Prior path: A, C, D, A New path: C, E, D, B, C 131


C A

D B

Prior result: A, C, D, A New result: C, E, D, B, C

Splice C
in prior path
Spliced result: A, C, E, D, B, C, D, A with
new path

132
Euler Circuit

1
2 C A

E 6
7 5
3 D B
4

Spliced result: A, C, E, D, B, C, D, A

133
End of Slides

134

Potrebbero piacerti anche