0% found this document useful (0 votes)
16 views68 pages

3 - 0 Graphs Basics

Uploaded by

Ravi Rane
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
16 views68 pages

3 - 0 Graphs Basics

Uploaded by

Ravi Rane
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 68

Graph Basics

&
Graph Algorithms
Graphs
● A graph G = (V, E)
■ V = set of vertices
■ E = set of edges = subset of V  V
■ Thus |E| = O(|V|2)
Applications

● Applications that involve not only a set of items, but also the
connections between them

Maps Schedules Computer networks

Hypertext Circuits
Graph Variations
● Variations:
■ A connected graph has a path from every vertex to
every other vertex
■ In an undirected graph:
○ Edge (u,v) = edge (v,u)
○ No self-loops
■ In a directed graph:
○ Edge (u,v) goes from vertex u to vertex v, notated uv
Graph Variations
● More variations:
■ A weighted graph associates weights with either
the edges or the vertices
○ E.g., a road map: edges might be weighted w/ distance
■ A multigraph allows multiple edges between the
same vertices
○ E.g., the call graph in a program (a function can get
called from multiple points in another function)
Directed Acyclic Graphs
● A directed acyclic graph or DAG is a directed
graph with no directed cycles:
Graphs
● We will typically express running times in
terms of |E| and |V|
■ If |E|  |V|2 the graph is dense
■ If |E|  |V| the graph is sparse
● If you know you are dealing with dense or
sparse graphs, different data structures may
make sense
Representing Graphs
● Assume V = {1, 2, …, n}
● An adjacency matrix represents the graph as a
n x n matrix A:
■ A[i, j] = 1 if edge (i, j)  E (or weight of
edge)
= 0 if edge (i, j)  E
Graphs: Adjacency Matrix
● Example:
A 1 2 3 4
1
a 1

2 d
4 2
3
b c
??
3 4
Graphs: Adjacency Matrix
● Example:
A 1 2 3 4
1
a 1 0 1 1 0

2 d
4 2 0 0 1 0
b c 3 0 0 0 0
3 4 0 0 1 0
Properties of Adjacency Matrix
Representation
● Memory required 1 2
■ (V2), independent on the number of edges in G 3
● Preferred when
■ The graph is dense: E is close to V 2 5 4
■ We need to quickly determine if there is
an edge between two vertices Undirected graph
● Time to determine if (u, v)  E:
■ (1) 1 2
● Disadvantage
■ No quick way to determine the vertices
3 4
adjacent to another vertex
● Time to list all vertices adjacent to u: Directed graph
■ (V)
Graph : Adjacency List
● Adjacency list representation of G = (V, E)
■ An array of V lists, one for each vertex in V
■ Each list Adj[u] contains all the vertices v that are
adjacent to u (i.e., there is an edge from u to v)
■ Can be used for both directed and undirected graphs
1 2 5 /
1 2 2 1 5 3 4 /

3 3 2 4
4 2 5 3 /
5 4
5 4 1 2
Undirected graph
Properties of Adjacency-List
Representation
● Sum of “lengths” of all adjacency lists 1 2
■ Directed graph: |E |
○ edge (u, v) appears only once
(i.e., in the list of u) 3 4
■ Undirected graph: 2|E | Directed graph
o edge (u, v) appears twice (i.e., in the
1 2
lists of both u and v)
3
5 4

Undirected graph
Properties of Adjacency-List
● Memory required
Representation
■ (V + E) 1 2
● Preferred when 3
■ The graph is sparse: E  << V 2
5 4
■ We need to quickly determine the nodes adjacent to a
given node. Undirected graph
● Disadvantage
■ No quick way to determine whether there is an edge
1 2
between node u and v
● Time to determine if (u, v)  E: 3 4
■ O(degree(u))
Directed graph
● Time to list all vertices adjacent to u:
■ (degree(u))
Graph Searching
● Given: a graph G = (V, E), directed or undirected
● Goal: methodically explore every vertex and
every edge
● Ultimately: build a tree on the graph
■ Pick a vertex as the root
■ Choose certain edges to produce a tree
■ Note: might also build a forest if graph is not
connected
Breadth-First Search
● “Explore” a graph, turning it into a tree
■ One vertex at a time
■ Expand frontier of explored vertices across the
breadth of the frontier
● Builds a tree over the graph
■ Pick a source vertex to be the root
■ Find (“discover”) its children, then their children,
etc.
Breadth-First Search
● We will associate vertex “colors” to guide the
algorithm
■ White vertices have not been discovered
○ All vertices start out white
■ Grey vertices are discovered but not fully explored
○ They may be adjacent to white vertices
■ Black vertices are discovered and fully explored
○ They are adjacent only to black and gray vertices

● Explore vertices by scanning adjacency list of


grey vertices
Breadth-First Search
BFS(G, s) {
initialize vertices;
Q = {s}; // Q is a queue (FIFO); initialize to s
while (Q is not empty) {
u = RemoveFront(Q);
for each v  u->adj {
if (v->color == WHITE)
v->color = GREY;
v->d = u->d + 1;
What does v->d represent?
Enqueue(Q, v);
}
u->color = BLACK;
}
}
Breadth-First Search: Example

r s t u

   

   
v w x y
Breadth-First Search: Example

r s t u

 0  

   
v w x y

Q: s
Breadth-First Search: Example

r s t u

1 0  

 1  
v w x y

Q: w r
Breadth-First Search: Example

r s t u

1 0 2 

 1 2 
v w x y

Q: r t x
Breadth-First Search: Example

r s t u

1 0 2 

2 1 2 
v w x y

Q: t x v
Breadth-First Search: Example

r s t u

1 0 2 3

2 1 2 
v w x y

Q: x v u
Breadth-First Search: Example

r s t u

1 0 2 3

2 1 2 3
v w x y

Q: v u y
Breadth-First Search: Example

r s t u

1 0 2 3

2 1 2 3
v w x y

Q: u y
Breadth-First Search: Example

r s t u

1 0 2 3

2 1 2 3
v w x y

Q: y
Breadth-First Search: Example

r s t u

1 0 2 3

2 1 2 3
v w x y

Q: Ø
BFS: The Code Again
BFS(G, s) {
initialize vertices; Touch every vertex: O(V)
Q = {s};
while (Q is not empty) {
u = RemoveFront(Q);
for each v  u->adj { u = every vertex, but only once
if (v->color == WHITE)
v->color = GREY;
So v = every vertexv->d = u->d + 1;
that appears in
some other vert’s Enqueue(Q, v);

adjacency }list
u->color = BLACK;
} What will be the running time?
}
Total running time: O(V+E)
BFS: The Code Again
BFS(G, s) {
initialize vertices;
Q = {s};
while (Q not empty) {
u = RemoveTop(Q);
for each v  u->adj {
if (v->color == WHITE)
v->color = GREY;
v->d = u->d + 1;
v->p = u;
Enqueue(Q, v);
}
u->color = BLACK; What will be the storage cost
} in addition to storing the tree?
}
Total space used:
O(max(degree(v))) = O(E)
Depth-First Search
● Depth-first search is another strategy for
exploring a graph
■ Explore “deeper” in the graph whenever possible
■ Edges are explored out of the most recently
discovered vertex v that still has unexplored edges
■ When all of v’s edges have been explored,
backtrack to the vertex from which v was
discovered
Depth-First Search
● Vertices initially colored white
● Then colored gray when discovered
● Then black when finished
Depth-First Search: The Code
DFS(G) DFS_Visit(u)
{ {
u->color = GREY;
for each vertex u  G->V
time = time+1;
{
u->d = time;
u->color = WHITE;
for each v  u->Adj[]
}
{
time = 0;
if (v->color == WHITE)
for each vertex u  G->V
DFS_Visit(v);
{
}
if (u->color == WHITE)
u->color = BLACK;
DFS_Visit(u);
time = time+1;
}
u->f = time;
}
}
Depth-First Search: The Code
DFS(G) DFS_Visit(u)
{ {
u->color = GREY;
for each vertex u  G->V
time = time+1;
{
u->d = time;
u->color = WHITE;
for each v  u->Adj[]
}
{
time = 0;
if (v->color == WHITE)
for each vertex u  G->V
DFS_Visit(v);
{
}
if (u->color == WHITE)
u->color = BLACK;
DFS_Visit(u);
time = time+1;
}
u->f = time;
}
}

What does u->d represent?


Depth-First Search: The Code
DFS(G) DFS_Visit(u)
{ {
u->color = GREY;
for each vertex u  G->V
time = time+1;
{
u->d = time;
u->color = WHITE;
for each v  u->Adj[]
}
{
time = 0;
if (v->color == WHITE)
for each vertex u  G->V
DFS_Visit(v);
{
}
if (u->color == WHITE)
u->color = BLACK;
DFS_Visit(u);
time = time+1;
}
u->f = time;
}
}

What does u->f represent?


Depth-First Search: The Code
DFS(G) DFS_Visit(u)
{ {
u->color = GREY;
for each vertex u  G->V
time = time+1;
{
u->d = time;
u->color = WHITE;
for each v  u->Adj[]
}
{
time = 0;
if (v->color == WHITE)
for each vertex u  G->V
DFS_Visit(v);
{
}
if (u->color == WHITE)
u->color = BLACK;
DFS_Visit(u);
time = time+1;
}
u->f = time;
}
}

Will all vertices eventually be colored black?


Depth-First Search: The Code
DFS(G) DFS_Visit(u)
{ {
u->color = GREY;
for each vertex u  G->V
time = time+1;
{
u->d = time;
u->color = WHITE;
for each v  u->Adj[]
}
{
time = 0;
if (v->color == WHITE)
for each vertex u  G->V
DFS_Visit(v);
{
}
if (u->color == WHITE)
u->color = BLACK;
DFS_Visit(u);
time = time+1;
}
u->f = time;
}
}

What will be the running time?


Depth-First Search: The Code
DFS(G) DFS_Visit(u)
{ {
u->color = GREY;
for each vertex u  G->V
time = time+1;
{
u->d = time;
u->color = WHITE;
for each v  u->Adj[]
}
{
time = 0;
if (v->color == WHITE)
for each vertex u  G->V
DFS_Visit(v);
{
}
if (u->color == WHITE)
u->color = BLACK;
DFS_Visit(u);
time = time+1;
}
u->f = time;
}
}
Running time: O(n2) because call DFS_Visit on each vertex,
and the loop over Adj[] can run as many as |V| times
Depth-First Search: The Code
DFS(G) DFS_Visit(u)
{ {
u->color = GREY;
for each vertex u  G->V
time = time+1;
{
u->d = time;
u->color = WHITE;
for each v  u->Adj[]
}
{
time = 0;
if (v->color == WHITE)
for each vertex u  G->V
DFS_Visit(v);
{
}
if (u->color == WHITE)
u->color = BLACK;
DFS_Visit(u);
time = time+1;
}
u->f = time;
}
}
BUT, there is actually a tighter bound.
How many times will DFS_Visit() actually be called?
Depth-First Search: The Code
DFS(G) DFS_Visit(u)
{ {
u->color = GREY;
for each vertex u  G->V
time = time+1;
{
u->d = time;
u->color = WHITE;
for each v  u->Adj[]
}
{
time = 0;
if (v->color == WHITE)
for each vertex u  G->V
DFS_Visit(v);
{
}
if (u->color == WHITE)
u->color = BLACK;
DFS_Visit(u);
time = time+1;
}
u->f = time;
}
}

So, running time of DFS = O(V+E)


DFS Example
source
vertex
DFS Example
source
vertex
d f
1 | | |

| |

| | |
DFS Example
source
vertex
d f
1 | | |

2 | |

| | |
DFS Example
source
vertex
d f
1 | | |

2 | |

3 | | |
DFS Example
source
vertex
d f
1 | | |

2 | |

3 | 4 | |
DFS Example
source
vertex
d f
1 | | |

2 | |

3 | 4 5 | |
DFS Example
source
vertex
d f
1 | | |

2 | |

3 | 4 5 | 6 |
DFS Example
source
vertex
d f
1 | 8 | |

2 | 7 |

3 | 4 5 | 6 |
DFS Example
source
vertex
d f
1 | 8 | |

2 | 7 |

3 | 4 5 | 6 |
DFS Example
source
vertex
d f
1 | 8 | |

2 | 7 9 |

3 | 4 5 | 6 |

What is the structure of the grey vertices?


What do they represent?
DFS Example
source
vertex
d f
1 | 8 | |

2 | 7 9 |10

3 | 4 5 | 6 |
DFS Example
source
vertex
d f
1 | 8 |11 |

2 | 7 9 |10

3 | 4 5 | 6 |
DFS Example
source
vertex
d f
1 |12 8 |11 |

2 | 7 9 |10

3 | 4 5 | 6 |
DFS Example
source
vertex
d f
1 |12 8 |11 13|

2 | 7 9 |10

3 | 4 5 | 6 |
DFS Example
source
vertex
d f
1 |12 8 |11 13|

2 | 7 9 |10

3 | 4 5 | 6 14|
DFS Example
source
vertex
d f
1 |12 8 |11 13|

2 | 7 9 |10

3 | 4 5 | 6 14|15
DFS Example
source
vertex
d f
1 |12 8 |11 13|16

2 | 7 9 |10

3 | 4 5 | 6 14|15
DFS: Kinds of edges
● DFS introduces an important distinction
among edges in the original graph:
■ Tree edge: encounter new (white) vertex
○ The tree edges form a spanning forest
○ Can tree edges form cycles?
DFS Example
source
vertex
d f
1 |12 8 |11 13|16

2 | 7 9 |10

3 | 4 5 | 6 14|15

Tree edges
DFS: Kinds of edges
● DFS introduces an important distinction
among edges in the original graph:
■ Tree edge: encounter new (white) vertex
■ Back edge: from descendent to ancestor
○ Encounter a grey vertex (grey to grey)
DFS Example
source
vertex
d f
1 |12 8 |11 13|16

2 | 7 9 |10

3 | 4 5 | 6 14|15

Tree edges Back edges


DFS: Kinds of edges
● DFS introduces an important distinction
among edges in the original graph:
■ Tree edge: encounter new (white) vertex
■ Back edge: from descendent to ancestor
■ Forward edge: from ancestor to descendent
○ Not a tree edge, though
○ From grey node to black node
DFS Example
source
vertex
d f
1 |12 8 |11 13|16

2 | 7 9 |10

3 | 4 5 | 6 14|15

Tree edges Back edges Forward edges


DFS: Kinds of edges
● DFS introduces an important distinction
among edges in the original graph:
■ Tree edge: encounter new (white) vertex
■ Back edge: from descendent to ancestor
■ Forward edge: from ancestor to descendent
■ Cross edge: between a tree or subtrees
○ From a grey node to a black node
DFS Example
source
vertex
d f
1 |12 8 |11 13|16

2 | 7 9 |10

3 | 4 5 | 6 14|15

Tree edges Back edges Forward edges Cross edges


DFS: Kinds of edges
● DFS introduces an important distinction
among edges in the original graph:
■ Tree edge: encounter new (white) vertex
■ Back edge: from descendent to ancestor
■ Forward edge: from ancestor to descendent
■ Cross edge: between a tree or subtrees
● Note: tree & back edges are important; most
algorithms don’t distinguish forward & cross
DFS And Graph Cycles
● Thm: An undirected graph is acyclic iff a DFS
yields no back edges
■ If acyclic, no back edges (because a back edge
implies a cycle
■ If no back edges, acyclic
○ No back edges implies only tree edges
○ Only tree edges implies we have a tree or a forest
○ Which by definition is acyclic

● Thus, can run DFS to find whether a graph has


a cycle
DFS And Cycles
● What will be the running time?
● A: O(V+E)
● We can actually determine if cycles exist in
O(V) time:
■ In an undirected acyclic forest, |E|  |V| - 1
■ So count the edges: if ever see |V| distinct edges,
must have seen a back edge along the way

You might also like