chapter 12 graph algorithms
TRANSCRIPT
Chapter 12Graph Algorithms
Graph can be regarded a structure that gener-
alizes tree, in the sense that, in a graph, there
could be more than one paths from one node
to another. For example,
In this chapter, we discuss the general concept
of the graph structure, and several practically
useful algorithms. We begin with a bit graph
theory.
1
Konigsberg Problem
In the town of Konigsberg, the river Pregel
flows around the island Kneiphofand and di-
vides into two. There are therefore four land
areas, which are connected by seven bridges.
The Konigsberg Problem is to determine if,
starting at one land area, it is possible to walk
across all the bridges exactly once and return
to the starting area.
2
Define a graph, K(= (V, E), as follows:
V = {v|v is a land.}E = {(v1, v2)|∃ a bridge between v1 and v2.}
Thus, the Konigsberg problem has a solution
iff there exists a circuit including every vertex in
V such that every edge in E is included exactly
once.
In general, if a graph has this property, it is
called an Eulerian graph.
Theorem (Euler, 1736) A connected graph is
Eulerian iff each and every vertex in the graph
has a even degree.
3
Does there exist...?
By Kn, we mean a graph with n vertices such
that between any two vertices, there exists ex-
actly one edge. There are exactly n(n−1)2 edges
in Kn.
If we label each edge with either red or green
in a K6,, does there exist either a red triangle
or a green one?
As there are 215 different ways to label K6, it
is not practical to try this out exhaustively.
4
There does exist...!
Consider v1, one of the six vertices. There are
exactly five edges connecting it with the other
five. An important observation is that at least
three edges will be labeled with the same color,
either red or green(?). Wlog, let it be red. Let
the vertices connected to v1 be v2, v3 and v4.
Consider the edges connecting v1, v2 and v3.
If any of the three edges is red, we have a
red triangle. Otherwise, all of the three edges
must be green, we have a green triangle.
5
The four-color problem
In map making, to distinguish the different re-
gions, it makes sense to use different colors to
color adjacent regions.
Obviously at least three colors are needed and
it can also been shown that three colors are
not sufficient, but five colors are.
It was conjectured that four colors are suf-
ficient, as well. This four-color problem re-
mained unsolved for over 100 years. In 1976,
Appel and Haken, by using a computer, proved
that this conjecture is true.
6
Traveling Salesman Problem
Holding a map, a salesman wants to schedule a
trip, in which he can visit all the towns without
any repetition. The question is whether this is
possible, and if it is, how to schedule this trip.
Define a graph, S(= (V, E), as follows:
V = {v|v is a town.}E = {(v1, v2)|∃ a road between v1 and v2.}
7
Thus the salesman problem has a solution iff
there exists a circuit such that it includes every
vertex in S exactly once.
In general, if a graph has this property, it is
called an Hamiltonian graph.
Even though the salesman problem looks quite
similar to the Konigsberg problem, there does
not exist a simple, useful and elegant solution.
Also, every known algorithm for this problem
is O(2n).
This is a major unsolved problem in graph the-
ory.
8
Graph terminology
Definition 1. A graph, G, is an ordered pair
(V, E). V is a set of vertices and E is a set of
edges. E = {(u, v)|u, v ∈ V }.
If for all (u, v) ∈ E, (u, v) is an ordered pair,
then G is a directed graph, or digraph; other-
wise, it is a undirected graph, or graph.
Vertices i and j are adjacent, if (i, j) ∈ E. The
edge (i, j) is also incident to vertices i and j.
The number of vertices incident to a vertex,
v, is defined to be the degree of that vertex,
denoted as d(v).
9
A weighted graph is a triplet, (V, E, ω). Here ω
is the weight function. For every edge, e ∈ E,
ω(e) is the weight assigned to the edge e.
For example, the following map is a weighted
graph.
10
By a subgraph, we mean part of a graph. More
formally, by saying that G1 is a subgraph of G2,
we mean V1 ⊂ V2 and E1 ⊂ E2. For example,
the following graph is a subgraph of the cam-
pus graph we saw before.
A subgraph of G that contains all the vertices
of G is called a spanning graph of G. If such a
subgraph is also a tree, it will then be called a
spanning tree.
11
Definition 2. Given a graph, G = (V, E). By
saying that p(= v1, . . . , vn) is a path in G, we
mean that for all i ∈ [1, n), (vi, vi+1) ∈ E. A
simple path is a path in which all the vertices,
except the first and the last, are different.
The length of p is defined as n − 1. If p is
empty, its length is defined as 0.
For every edge in a (di)graph, we can associate
it with a length. The length of a path is then
defined to be the sum of the lengths of all the
edges in that path. We are often interested in
finding out the shortest path from one vertex
to another.
12
Definition 3. Given G = (V, E), a digraph. By
a cycle, we mean a path in G with at least one
edge and w1 = wn. Call it a simple circle, if
the path is simple.
A digraph is acyclic if it has no cycles.
Definition 4. Given G = (V, E), a graph. By
saying that G is connected, we mean that for
all u and v ∈ V , there is a path between u and
v. Otherwise, G is disconnected.
If G is a digraph and it satisfies the above
property, we say it is strongly connected. If
a digraph is not strongly connected, but its
underlying graph is connected, we say that the
digraph is weakly connected.
13
A connected graph that contains no cycles is
called a tree.
Lemma: Let T be a tree. Then it has at least
two leaves.
Theorem: Let T be a finite tree containing n
vertices. Then it has n − 1 edge.
Definition 5. Given G = (V, E). By saying
that G is complete, we mean that ∀u, v ∈ V ,
(u, v) ∈ E.
A complete graph with n nodes has n(n−1)2
edges.
14
Application
Airport system can be represented as a weighted
digraph.
A = (V, E, ω)
V = {a|a is an airport. }E = {(a1, a2)|∃ non-stop flight from a1 to a2.}
For e ∈ E, ω(e) could be cost, time, . . . .
To have a effective transportation system, we
may expect a strongly connected digraph. To
have a efficient system, we may want to find
out the “best” travel plan, e.g., the shortest
path from one town to another.
15
Properties
Property 1: Let G(= (V, E) be a graph. Let
|V | = n, |E| = e, and di denote the degree of
vi. Then
n∑
i=1
di = 2e, and, (1)
0 ≤ e ≤n(n − 1)
2. (2)
Proof: Eq. 1 is true since every edge is inci-
dent to exactly two vertices, hence contribut-
ing 2 to the sum.
Obviously, when a graph is empty, e = 0. On
the other hand, a vertex is adjacent to at most
n− 1 other vertices, each of which leads to an
edge. Hence the maximum number of edges
will be n(n−1)2 , whence the factor of 2 takes
into consideration the fact that every edge is
counted twice.
16
Let G be a digraph, dini , the in-degree of a
vertex, v, is defined to be the number of edges
coming into v. We have a similar definition of
out-degree of v.
Property 2: Let G(= (V, E) be a digraph. Let
|V | = n, |E| = e, and di denote the degree of
vi. Then
n∑
i=1
dini =
n∑
i=1
douti ,and, (3)
0 ≤ e ≤ n(n − 1). (4)
The proofs are similar to the previous one.
17
Homework
12.1. In the following graph, find out the in-
degree, and out-degree, of each vertex, the
set of vertices adjacent from vertex 2, those
adjacent to vertex 1, incident from vertex 3
and those incident to vertex 4, as well as all
directed cycles and their lengths.
12.2. Prove the above property 2.
18
12.3. Let G be any undirected graph. Show
that the number of vertices with odd degree is
even.
12.4. Let G = (V, E)) be a connected graph
with |V | > 1. Show that G contains either a
vertex of degree 1 or a cycle (or both).
12.5. Let G = (V, E) be a connected graph
and contains at least one cycle. Let (i, j) ∈ E
be an edge that is on at least one cycle of G.
Show that G − {(i, j)} is also connected.
19
12.6. Prove the following: (i) For every n ≥ 1,
there exists a connected undirected graph con-
taining exactly n−1 edges. (ii) Every n−vertex
connected undirected graph contains at least
n − 1 edges.
12.7. A digraph is strongly connected iff it
contains a directed path from i to j and from
j to i for every pair of distinct vertices i and
j. (i) Show that for every n ≥ 2, there exists a
strongly connected digraph that contains ex-
actly n edges. (ii) Show that every n vertex
strongly connected digraph contains at least
n ≥ 2 edges.
20
Graph representation
Usually, a graph can be represented as eitheran adjacency matrix, or an adjacency list.
The adjacency matrix of an n−vertex graph,G, is an n × n matrix, such that,
A(i, j) =
{1 if (i, j) ∈ E,or (j, i) ∈ E0 otherwise.
It is easy to see, such a matrix must be sym-metric.
Similarly, the adjacency matrix of an n−vertexdigraph, G, is an n × n matrix, such that,
A(i, j) =
{1 if (i, j) ∈ E0 otherwise.
It is also easy to see thatn∑
j=1
A(i, j) = douti ,and,
n∑
i=1
A(i, j) = dinj .
21
Linked-adjacency list
Adjacency matrix is easy to use, but it uses
Θ(n2) space, which can be reduced. An alter-
native approach is to use a chain to represent,
for every vertex, all the vertices it is adjacent.
If |v| = n, |E| = e, such a representation uses
Θ(n+m), whence m = 2e, when G is a graph,
m = e otherwise.
22
Homework
12.8. For the graphs given for Exercise 12.1,
obtain their representation as adjacency ma-
trix, and linked-adjacency lists.
12.9. Let a be an (n − 1) × n array that rep-
resents the adjacency matrix A of an n−vertex
graph. The matrix diagonal is not represented
in a. Write functions Store and Retrieve to,
respectively, store and retrieve the values of
A(i, j), with complexities being Θ(1).
12.10. Assume a directed n×n adjacency ma-
trix is represented in an n × n array a. Write
functions that will determine the out-degree
and indegree of a vertex in such a graph, with
their complexities being Θ(n). Also, write a
function to determine the number of edges.
23
Representation of networks
Networks are nothing but digraphs with each
of its edges labeled with some weight. For a
transportation network, the label of each of its
edge can be the distance from one location to
another, etc..
Hence, when we use the aforementioned meth-
ods to represent a network, we have to add one
more field, to keep the weight information.
24
A little assignment
Homework 12.11. Write a procedure to deter-
mine whether or not the digraph G is strongly
connected.
Analyze the time complexity of the just created
procedure for the case that G is represented as
an adjacency matrix and as a linked-adjacency-
list representation, respectively.
25
The graph classes
Both graphs and digraphs can be regarded as
special networks, when we regard those un-
weighted edges have the same weight of, e.g.,
1. Hence, we will declare a general class for
the data type of network, and then derive more
specific ones from this base class.
26
The base class
class AdjacencyWDigraph {
friend AdjacencyWGraph<T>;
public:
AdjacencyWDigraph
(int Vertices = 10, T noEdge = 0);
~AdjacencyWDigraph(){Delete2DArray(a,n+1);}
bool Exist(int i, int j) const;
int Edges() const {return e;}
int Vertices() const {return n;}
AdjacencyWDigraph<T>& Add
(int i, int j, const T& w);
AdjacencyWDigraph<T>& Delete(int i, int j);
int OutDegree(int i) const;
int InDegree(int i) const;
void Output() const;
private:
T NoEdge; // used for absent edge
int n; // number of vertices
int e; // number of edges
T **a; // 2D array
};
27
Some of the operations
AdjacencyWDigraph<T>
::AdjacencyWDigraph(int Vertices,T noEdge){
n = Vertices;
e = 0;
NoEdge = noEdge;
Make2DArray(a, n+1, n+1);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
a[i][j] = NoEdge;
}
bool AdjacencyWDigraph<T>::
Exist(int i, int j) const{
if (i < 1 || j < 1 || i > n || j > n
|| a[i][j] == NoEdge) return false;
return true;
}
28
AdjacencyWDigraph<T>& AdjacencyWDigraph<T>
::Add(int i, int j, const T& w){
if (i < 1 || j < 1 || i > n ||
j > n || i == j || a[i][j] != NoEdge)
throw BadInput();
a[i][j] = w;
e++;
return *this;
}
AdjacencyWDigraph<T>& AdjacencyWDigraph<T>
::Delete(int i, int j){
if (i < 1 || j < 1 || i > n ||
j > n || a[i][j] == NoEdge)
throw BadInput();
a[i][j] = NoEdge;
e--;
return *this;
}
29
A derived class for graphs
Once the network is declared, we can derive
various classes. For example, below declares a
class for weighted graph.
class AdjacencyWGraph
: public AdjacencyWDigraph<T> {
public:
AdjacencyWGraph(int Vertices=10,T noEdge=0)
:AdjacencyWDigraph<T>(Vertices,noEdge){}
AdjacencyWGraph<T>& Add(int i,int j,const T&w)
{AdjacencyWDigraph<T>::Add(i,j,w);
a[j][i] = w;
return *this;}
AdjacencyWGraph<T>& Delete(int i,int j)
{AdjacencyWDigraph<T>::Delete(i,j);
a[j][i] = NoEdge;
return *this;}
int Degree(int i) const {return OutDegree(i);}
};
30
The LinkedBase class
Similarly, we will provide a base class for thelinked representation of a network, and derivethe rest.
class LinkedBase {
public:
LinkedBase(int Vertices = 10){
n = Vertices; e = 0;
h = new Chain<T> [n+1];}
~LinkedBase() {delete [] h;}
int Edges() const {return e;}
int Vertices() const {return n;}
int OutDegree(int i) const{
if (i < 1 || i > n) throw OutOfBounds();
return h[i].Length();}
void Output() const;
private:
int n; // number of vertices
int e; // number of edges
Chain<T> *h; // adjacency list array
};
31
A derived class for graphs
We can derive various classes, based on theLinkedBased class. The following is the linked
representation of digraphs.
class LinkedDigraph:public LinkedBase<int> {
public:
LinkedDigraph(int Vertices = 10)
: LinkedBase<int> (Vertices) {}
bool Exist(int i, int j) const;
LinkedDigraph& Add(int i, int j);
LinkedDigraph& Delete(int i, int j);
int InDegree(int i) const;
protected:
LinkedDigraph& AddNoCheck(int i, int j);
};
bool LinkedDigraph::Exist(int i, int j) const{
if (i < 1 || i > n) throw OutOfBounds();
return (h[i].Search(j)) ? true : false;
}
32
Additional operations
LinkedDigraph& LinkedDigraph::
Add(int i,int j){
if (i < 1 || j < 1 || i > n || j > n || i == j
|| Exist(i, j)) throw BadInput();
return AddNoCheck(i, j);
}
LinkedDigraph& LinkedDigraph::
Delete(int i,int j){
if (i < 1 || i > n) throw OutOfBounds();
h[i].Delete(j); e--;
return *this;
}
int LinkedDigraph::InDegree(int i) const{
if (i < 1 || i > n) throw OutOfBounds();
int sum = 0;
for (int j = 1; j <= n; j++)
if (h[j].Search(i)) sum++;
return sum;
}
33
Iterators
We often need, for a vertex, find out the next
vertex it is adjacent to. Such operations are
collected to be the class of iterators. For ex-
ample, the following are iterators for the ad-
jacency matrixes, whence the array pos[i+1]
is used to keep the position, for vi, the first
vertex it is adjacent to.
int AdjacencyWDigraph<T>::Begin(int i){
if (i < 1 || i > n) throw OutOfBounds();
for (int j = 1; j <= n; j++)
if (a[i][j] != NoEdge) {
pos[i] = j; return j;}
pos[i] = n + 1; // no adjacent vertex
return 0; }
34
The following operation finds out the next ver-
tex to which vi is adjacent.
int AdjacencyWDigraph<T>::NextVertex(int i){
if (i < 1 || i > n) throw OutOfBounds();
for (int j = pos[i] + 1; j <= n; j++)
if (a[i][j] != NoEdge) {
pos[i] = j; return j;}
pos[i] = n + 1; // no next vertex
return 0;
}
35
Search in graphs
There are two primary graph traversal schemes:
Depth-First and Breadth-First Traversals.
In BFS, every vertex adjacent to the current
vertex is visited first before we move away from
it. We will accomplish this by keeping the ad-
jacent vertices that have not been visited in a
queue.
In DFS, we mark a vertex as soon as it is visited
and then try to move to an unmarked adjacent
vertex. If there are no unmarked vertices left,
we backtrack along the vertices we have al-
ready visited until we come to a vertex that is
adjacent to an unvisited one, visit that one and
continue the process. There is a stack behind
DFS.
36
BFS Algorithm
Begin at vertex v;
label v as reached;
Initialize Q, which contains only v;
while( Q is not empty){
Delete a vertex w from Q;
while(there is a u adjacent to w;
If (u is not labeled) {
Add u to the queue;
label u as reached;
}
}
37
DFS Algorithm
It is natural to follow a recursive approach to
do a depth first search.
void Network::DFS(int v,int reach[],int label)
{// Depth first search driver.
InitializePos(); // init graph iterator array
dfs(v, reach, label); // do the dfs
DeactivatePos(); // free graph iterator array
}
void Network::dfs(int v,int reach[],int label)
{// Actual depth-first search code.
reach[v] = label;
int u = Begin(v);
while (u) {// u is adj to v
if (!reach[u]) dfs(u, reach, label);
u = NextVertex(v);}
}
38
Complexities
For BFS, for each node that is labeled, it is
enqueued and dequeued exactly once, and its
row (if implemented as an adjacency matrix),
otherwise its list, is visited exactly once. This
is the same for DFS. Hence, when stored in
an adjacency matrix, the total time complexity
for both DFS and BFS is O(sn), where s is the
number of nodes that are labeled; otherwise,
it will take∑
i douti , where the sum is done over
the indexes of all the nodes that are labeled.
As far as the space complexity is concerned,
the best case for BFS, where the graph is a
list, is just the worst for DFS. They need 1
and n, respectively. On the other hand, the
best case for DFS, where the graph is a 1 level
full tree, is the worst for BFS.
39
Path finding
Given a graph, and two of its vertices, v and w.
We can use either BFS and DFS to look for a
path from v to w. If we also want to constructthe path later, it is more natural to use DFS.
bool Network::FindPath
(int v, int w, int &length, int path[]){
path[0] = v;
length = 0; // current path length
if (v == w) return true;
int n = Vertices();
InitializePos(); // iterator
int *reach = new int [n+1];
for (int i = 1; i <= n; i++)
reach[i] = 0;
bool x = findPath(v, w, length, path, reach);
DeactivatePos();
delete [] reach;
return x;
}
40
The actual finder
bool Network::findPath(int v,int w,int &length,
int path[], int reach[])
{//Actual path finder v != w.
//Performs a DFS for a path to w.
reach[v] = 1;
int u = Begin(v);
while (u) {
if(!reach[u]) {
length++;
path[length] = u; // add u to path
if(u == w) return true;
if(findPath(u, w, length, path, reach))
return true;
// no path from u to w
length--; // remove u
}
u = NextVertex(v);}
return false;
}
41
Connectedness
We can check if a graph is connected, by ap-
plying either BFS or DFS to it, starting with
any vertex, v. If at the end, all the vertices get
labeled, it must be connected; otherwise, it is
not.
When a graph is not connected, the set of ver-
tices that are reachable from a vertex is called
a connected component. The problem of com-
ponent labeling is to label all the vertices of the
same component with the same label. This
can also be done by using either BFS or DFS.
We label a vertex first, and assign the same la-
bel during the search. If at the end, all vertices
get labeled, we used only one label. Otherwise,
we start with the fist unlabeled vertex, using
the next label.
42
Topological sort
Given an acyclic digraph, G(= (V, E)). By a
topological sort of G on V, we mean an or-
dering of all members of V s.t. if there is a
path from vi to vj, then vi precedes vj in the
sort. Sequences that satisfy this property are
topological orders, or topological sequences.
A topological ordering of all courses leads to a
sequence which won’t violate the prerequisite
requirement. Another example is the assembly
task, in which some parts must be put together
first, before other tasks can be performed.
43
A couple of notes
1. If the given digraph is not acyclic, then no
topological sort exists.(?)
2. There could be more than one such sort
for a given acyclic graph. For example, v1, v2,
v5, v4, v3, v7, v6 and v1, v2, v5, v4, v7, v3, v6 are
both topological sort for the following graph.
44
A simple algorithm
Given a digraph G and v ∈ V. By an edge com-
ing into v, we mean any edge (u, v) ∈ E. By
an edge outgoing from v, we mean any edge
(v, w) ∈ E.
The following is an algorithm looking for a
topological sorting in G. *
while not all vertices labeled yet {
find v, s.t. there is no edge coming into v;
label v with the next available number;
retract v together with all edges outgoing
from v;
end;
45
Correctness
Lemma If G is a finite acyclic digraph, there
exists a vertex in G such that no edge comes
into it.
Proof: Just assume all vertices having edges
coming into it. Let v1 be such a vertex. So, for
some v2, (v2, v1) ∈ E. Similarly, for v3, · · · , vn, · · ·,we have that (vi+1, vi) ∈ E. As G is finite, for
some i, j, vi = vj. Thus, G cannot be acyclic.
Theorem If G is a finite, acyclic digraph, then
the algorithm gives the topological sorting.
46
Proof: Let vi and vj be two vertices such that
there is a path from vi to vj. To show that vj
cannot be labeled unless vi gets labeled first.
Inducting on the length of the path from vi to
vj. If the length is 1, i.e., (vi, vj) ∈ E. Then
vj gets labeled only if every edge coming into
vj, particularly (vi, vj), has been retracted. By
the algorithm, this won’t happen unless vi is
retracted, after its labeling.
In general, let vi, vi+1, · · · , vj be a path of G.
Similar argument shows that vi+1 will be la-
beled after the labeling of vi. Also, inductive
assumption shows that vj won’t be labeled un-
less vi+1 gels labeled first. Thus, vj won’t be
labeled unless vi gets labeled first.
47
Implementation
Let G = (V, E), and let v ∈ V. By din(v), the in
degree of v, is defined as the number of edges
coming into v.
void Toposort(G: graph){
for(c=1; c<=|V|; c++){
find v such that its indegree is 0;
if (v==0) error;
else {
top_num[v]=c;
for each w adjacent to v do
indegree[w]=indegree[w]-1;
}
}
}
This algorithm takes O(|V |2). It can be im-
proved, as we only need to check for those
nodes whose indegree is just decremented to
see if it is 0.48
bool Network::Topological(int v[]){
int n = Vertices(), *InDegree = new int [n+1];
int InitializePos();
for (int i = 1; i <= n; i++) InDegree[i] = 0;
for (i = 1; i <= n; i++) {
int u = Begin(i);
while(u){ InDegree[u]++;u = NextVertex(i);}
}
LinkedStack<int> S;
for (i = 1; i <= n; i++)
if (!InDegree[i]) S.Add(i);
i = 0;
while (!S.IsEmpty()) {
int w; S.Delete(w);
v[i++] = w; int u = Begin(w);
while (u) {
InDegree[u]--;
if (!InDegree[u]) S.Add(u);
u = NextVertex(w);} }
DeactivatePos();
delete [] InDegree;
return (i == n);
}
50
Algorithm analysis
For the first and third for loop, we have to
process every node once, thus, Θ(n).
For the second for loop, if we use adjacency
matrix, it will take O(n2). But, if linked adja-
cency list is used, then it will take∑
v(|Ev| +1) = O(|V | + |E|). The same analysis applied
to the nested while loop.
51