0% found this document useful (0 votes)
2 views54 pages

07 - APS - Graph

The document provides an overview of graphs as a data structure consisting of nodes and edges, including definitions of directed and undirected graphs, complete graphs, and cycles. It discusses various graph representations such as adjacency lists, adjacency matrices, and edge lists, along with their space complexities. Additionally, it introduces the breadth-first search algorithm for traversing graphs, detailing its operations and examples.

Uploaded by

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

07 - APS - Graph

The document provides an overview of graphs as a data structure consisting of nodes and edges, including definitions of directed and undirected graphs, complete graphs, and cycles. It discusses various graph representations such as adjacency lists, adjacency matrices, and edge lists, along with their space complexities. Additionally, it introduces the breadth-first search algorithm for traversing graphs, detailing its operations and examples.

Uploaded by

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

Algorithms & data structures

Graph
Damjan Strnad
2

Graf

a graph is a data structure G=(V,E) consisting of a set of
nodes V and a set E of edges (i.e., node pairs) between
nodes

example: G=({a,b,c,d,e},{(a,b),(a,c),(b,d),(b,e),(c,d),(d,e)})
a b

c d


linked lists and trees are special cases of graphs
a

a b d c b c

d e
3

Graf

a graph can be undirected (edges are unordered pairs of
nodes) or directed (first node of the edge is the source and
the second node is the destination)

example: G=({a,b,c,d,e},{(a,b),(a,c),(c,a),(d,b),(b,e),(c,d),e,d)})
– the order of nodes in edge
a b
notation is now important
e


a complete graph is a graph in c d

which every node is connected to every other node:


– there are n(n+1)/2 edges in a complete graph with n nodes

the degree of a node is the number of its neighbors:
– in a directed graph (digraph) we distinguish node
in-degree and out-degree
4

Graph
● a path in a graph is every sequence of edges (v1,v2),
(v2,v3), … , (vr-1,vr)

a simple path is a path that visits each intermediate node
only once

a closed simple path is a cycle

a cycle going through all nodes of a graph is a
Hamiltonian cycle

an acyclic graph is a graph that contains no cycles

a graph is connected, if there is a path between every
pair of nodes

a graph is weighted, if edges have assigned weights or
costs; w(u,v) is a weight of edge from u to v
5

Graph representation

representation with adjacency lists:
– suitable for sparse graphs for which |E|≪|V|2
– consists of an array Adj which for every graph node u∈V
stores a pointer to a linked list of node‘s neighbors**
– for weighted graphs the edge weight is stored in the nodes
of the linked list
– space complexity for a graph with n nodes is
S(n)=O(|V|+|E|)
A
1 2 1 2 5
2 1 3 4 5
3
3 2 4 5
4 2 3 5
5 4
5 1 2 3 4
6

Graph representation

representation with adjacency lists:
– suitable for sparse graphs for which |E|≪|V|2
– consists of an array Adj which for every graph node u∈V
stores a pointer to a linked list of node‘s neighbors**
– for weighted graphs the edge weight is stored in the nodes
of the linked list
– space complexity for a graph with n nodes is
S(n)=O(|V|+|E|)
A
1 2 1 2
2 3
3
3 5
4 2 3
5 4
5 1 2 4
7

Graph representation

representation with adjacency lists:
– suitable for sparse graphs for which |E|≪|V|2
– consists of an array Adj which for every graph node u∈V
stores a pointer to a linked list of node‘s neighbors**
– for weighted graphs the edge weight is stored in the nodes
of the linked list
– space complexity for a graph with n nodes is
S(n)=O(|V|+|E|)
3 A
1 2 1 2 3
1
7 2 3 1
1 4 3
3 3 5 3
2 4 2 4 3 2
5 4
8 5 1 1 2 7 4 8
8

Graph representation

representation with adjacency matrix:
– suitable for dense graphs for which |E|≈|V|2
– graph nodes are enumerated using indices from 1 to |V|
– adjacency matrix A is of size |V|×|V|, where element aij
determines if there is an edge going from node i to node j:

{
aij = 1 , if (i , j)∈E
0 , otherwise
– space complexity is S(n)=Θ(|V|2)

[ ]
1 2 0 1 0 0 1
1 0 1 1 1
3 A= 0 1 0 1 1
0 1 1 0 1
5 4 1 1 1 1 0
9

Graph representation

representation with adjacency matrix:
– suitable for dense graphs for which |E|≈|V|2
– graph nodes are enumerated using indices from 1 to |V|
– adjacency matrix A is of size |V|×|V|, where element aij
determines if there is an edge going from node i to node j:

{
aij = 1 , if (i , j)∈E
0 , otherwise
– space complexity is S(n)=Θ(|V|2)

[ ]
1 2
0 1 0 0 0
0 0 1 0 0
3 A= 0 0 0 0 1
0 1 1 0 0
5 4 1 1 0 1 0
10

Graph representation

representation with adjacency matrix:
– for weighted graphs we use:

{
aij = w (i , j), if (i , j)∈E
∞ , otherwise

[ ]
3
1 2 ∞ 3 ∞ ∞ ∞
1
∞ ∞ 1 ∞ ∞
1 7 4 A= ∞ ∞ ∞ ∞ 3
3
3 ∞ 4 2 ∞ ∞
2
5 4 1 7 ∞ 8 ∞
8
11

Graph representation

representation with edge list:
– suitable for very sparse graphs and algorithms that iterate over
edges (Prim’s algorithm)
– the list stores edges as pairs (u,v)
– for weighted graphs the list elements are triplets (u,v,w)
– the space complexity is S(n)=O(|E|)
1 2

5 4

1 2 1 5 2 3 2 4 2 5 3 4 3 5 4 5
12

Graph representation

representation with edge list:
– suitable for very sparse graphs and algorithms that iterate over
edges (Prim’s algorithm)
– the list stores edges as pairs (u,v)
– for weighted graphs the list elements are triplets (u,v,w)
– the space complexity is S(n)=O(|E|)
3
1 2
1

1 7 4 3
3
2
5 4
8

1 2 3 5 1 1 4 2 4 5 4 8 2 3 1 5 2 7 3 5 3 4 3 2
13

Breadth-first search

breadth-first search (BFS) is one of basic algorithms for
searching in graphs:
– we are given a graph G=(V,E) with source node s
– the algorithm systematically follows graph edges and
discovers nodes which are reachable from s
– the first found path from s to arbitrary node v is also the
shortest one if the cost of all edges is the same
– the basic operation is node expansion, where we record
all node‘s successors which have not been recorded before
– the node‘s color shows its status:

white nodes have not yet been visited (initial state of all
nodes except source node s)

gray nodes have already been visited

black nodes have already been expanded (i.e., all
successors have already been visited)
14

Breadth-first search
● for each node v we store its color (color[v]), pointer to
parent (parent[v]) and distance (i.e., the number of edges,
d[v]) from source s

expansion sequence is determined by position in a queue, into
which the newly generated (i.e., gray) nodes are added
BREADTH-FIRST-SEARCH(G,s)
for each node u ∈ V – {s} do
color[u] ← WHITE, d[u] ← ∞, parent[u] ← NIL
color[s] ← GRAY, d[s] ← 0, parent[s] ← NIL
Q ← ∅
ENQUEUE(Q,s)
while Q ≠ ∅ do % while queue Q is not empty
u ← DEQUEUE(Q) % remove first node in queue
for each node v ∈ Adj[u] do % check all neighbours of u
if color[v] = WHITE then
color[v] ← GRAY, d[v] ← d[u] + 1, parent[v] ← u
ENQUEUE(Q,v)
color[u] ← BLACK % node u is expanded
15

Breadth-first search – example



let the source node be 2 1 7

assume the neighbors are 6
2 8
enqueued by increasing node
labels when some node is 4
5
3
expanded

inicialization: Q 2
– all nodes are colored white,
their distance from source set u color[u] parent[u] d[u]
to ∞, and pointers to parents 1 w NIL ∞
set to NIL 2 g NIL 0
3 w NIL ∞
– the source node is colored 4 w NIL ∞
gray, assigned distance 0 and 5 w NIL ∞
enqueued in Q 6 w NIL ∞
7 w NIL ∞
8 w NIL ∞
16

Breadth-first search – example



1. iteration: expand node 2* 1 7
6
2 8
5
3 4

Q 2
u color[u] parent[u] d[u]
1 w NIL ∞
2 g NIL 0
3 w NIL ∞
4 w NIL ∞
5 w NIL ∞
6 w NIL ∞
7 w NIL ∞
8 w NIL ∞
17

Breadth-first search – example



1. iteration: expand node 2* 1 7
6
2 8
5
3 4

Q 1 3 8
u color[u] parent[u] d[u]
1 g 2 1
2 b NIL 0
3 g 2 1
4 w NIL ∞
5 w NIL ∞
6 w NIL ∞
7 w NIL ∞
8 g 2 1
18

Breadth-first search – example



1. iteration: expand node 2 1 7

2. iteration: expand node 1* 6
2 8
5
3 4

Q 1 3 8
u color[u] parent[u] d[u]
1 g 2 1
2 b NIL 0
3 g 2 1
4 w NIL ∞
5 w NIL ∞
6 w NIL ∞
7 w NIL ∞
8 g 2 1
19

Breadth-first search – example



1. iteration: expand node 2 1 7

2. iteration: expand node 1* 6
2 8
5
3 4

Q 3 8 7
u color[u] parent[u] d[u]
1 b 2 1
2 b NIL 0
3 g 2 1
4 w NIL ∞
5 w NIL ∞
6 w NIL ∞
7 g 1 2
8 g 2 1
20

Breadth-first search – example



1. iteration: expand node 2 1 7

2. iteration: expand node 1 6
2 8

3. iteration: expand node 3*
5
3 4

Q 3 8 7
u color[u] parent[u] d[u]
1 b 2 1
2 b NIL 0
3 g 2 1
4 w NIL ∞
5 w NIL ∞
6 w NIL ∞
7 g 1 2
8 g 2 1
21

Breadth-first search – example



1. iteration: expand node 2 1 7

2. iteration: expand node 1 6
2 8

3. iteration: expand node 3*
5
3 4

Q 8 7 4
u color[u] parent[u] d[u]
1 b 2 1
2 b NIL 0
3 b 2 1
4 g 3 2
5 w NIL ∞
6 w NIL ∞
7 g 1 2
8 g 2 1
22

Breadth-first search – example



1. iteration: expand node 2 1 7

2. iteration: expand node 1 6
2 8

3. iteration: expand node 3
5

4. iteration: expand node 8* 3 4

Q 8 7 4
u color[u] parent[u] d[u]
1 b 2 1
2 b NIL 0
3 b 2 1
4 g 3 2
5 w NIL ∞
6 w NIL ∞
7 g 1 2
8 g 2 1
23

Breadth-first search – example



1. iteration: expand node 2 1 7

2. iteration: expand node 1 6
2 8

3. iteration: expand node 3
5

4. iteration: expand node 8* 3 4

Q 7 4
u color[u] parent[u] d[u]
1 b 2 1
2 b NIL 0
3 b 2 1
4 g 3 2
5 w NIL ∞
6 w NIL ∞
7 g 1 2
8 b 2 1
24

Breadth-first search – example



1. iteration: expand node 2 1 7

2. iteration: expand node 1 6
2 8

3. iteration: expand node 3
5

4. iteration: expand node 8 3 4

5. iteration: expand node 7*
Q 7 4
u color[u] parent[u] d[u]
1 b 2 1
2 b NIL 0
3 b 2 1
4 g 3 2
5 w NIL ∞
6 w NIL ∞
7 g 1 2
8 b 2 1
25

Breadth-first search – example



1. iteration: expand node 2 1 7

2. iteration: expand node 1 6
2 8

3. iteration: expand node 3
5

4. iteration: expand node 8 3 4

5. iteration: expand node 7*
Q 4 6
u color[u] parent[u] d[u]
1 b 2 1
2 b NIL 0
3 b 2 1
4 g 3 2
5 w NIL ∞
6 g 7 3
7 b 1 2
8 b 2 1
26

Breadth-first search – example



1. iteration: expand node 2 1 7

2. iteration: expand node 1 6
2 8

3. iteration: expand node 3
5

4. iteration: expand node 8 3 4

5. iteration: expand node 7

6. iteration: expand node 4* Q 4 6
u color[u] parent[u] d[u]
1 b 2 1
2 b NIL 0
3 b 2 1
4 g 3 2
5 w NIL ∞
6 g 7 3
7 b 1 2
8 b 2 1
27

Breadth-first search – example



1. iteration: expand node 2 1 7

2. iteration: expand node 1 6
2 8

3. iteration: expand node 3
5

4. iteration: expand node 8 3 4

5. iteration: expand node 7

6. iteration: expand node 4* Q 6 5
u color[u] parent[u] d[u]
1 b 2 1
2 b NIL 0
3 b 2 1
4 b 3 2
5 g 4 3
6 g 7 3
7 b 1 2
8 b 2 1
28

Breadth-first search – example



1. iteration: expand node 2 1 7

2. iteration: expand node 1 6
2 8

3. iteration: expand node 3
5

4. iteration: expand node 8 3 4

5. iteration: expand node 7

6. iteration: expand node 4 Q 6 5

7. iteration: expand node 6* u color[u] parent[u] d[u]
1 b 2 1
2 b NIL 0
3 b 2 1
4 b 3 2
5 g 4 3
6 g 7 3
7 b 1 2
8 b 2 1
29

Breadth-first search – example



1. iteration: expand node 2 1 7

2. iteration: expand node 1 6
2 8

3. iteration: expand node 3
5

4. iteration: expand node 8 3 4

5. iteration: expand node 7

6. iteration: expand node 4 Q 5

7. iteration: expand node 6* u color[u] parent[u] d[u]
1 b 2 1
2 b NIL 0
3 b 2 1
4 b 3 2
5 g 4 3
6 b 7 3
7 b 1 2
8 b 2 1
30

Breadth-first search – example



1. iteration: expand node 2 1 7

2. iteration: expand node 1 6
2 8

3. iteration: expand node 3
5

4. iteration: expand node 8 3 4

5. iteration: expand node 7

6. iteration: expand node 4 Q 5

7. iteration: expand node 6 u color[u] parent[u] d[u]

8. iteration: expand node 5* 1 b 2 1
2 b NIL 0
3 b 2 1
4 b 3 2
5 g 4 3
6 b 7 3
7 b 1 2
8 b 2 1
31

Breadth-first search – example



1. iteration: expand node 2 1 7

2. iteration: expand node 1 6
2 8

3. iteration: expand node 3
5

4. iteration: expand node 8 3 4

5. iteration: expand node 7

6. iteration: expand node 4 Q

7. iteration: expand node 6 u color[u] parent[u] d[u]

8. iteration: expand node 5* 1 b 2 1
2 b NIL 0
3 b 2 1
4 b 3 2
5 b 4 3
6 b 7 3
7 b 1 2
8 b 2 1
32

Breadth-first search – example



the working of BFS can be summarized in a table
iteration expanded node u parent[u] d[u]
1 2 NIL 0
2 1 2 1
3 3 2 1
4 8 2 1
5 7 1 2
6 4 3 2
7 6 7 3
8 5 4 3
33

Breadth-first search – example



with the help of pointers to parents we can build the search
tree of BFS
u color[u] parent[u] d[u]
2 1 b 2 1
2 b NIL 0
1 3 8 3 b 2 1
4 b 3 2
7 4 5 b 4 3
6 b 7 3
6 5 7 b 1 2
8 b 2 1
34

Depth-first search

depth-first search (DFS) is similar to breadth-first search
but uses a stack instead of a queue for storing gray nodes
DEPTH-FIRST-SEARCH(G,s)
for each node u ∈ V – {s} do
color[u] ← WHITE, d[u] ← ∞, parent[u] ← NIL
color[s] ← GRAY, d[s] ← 0, parent[s] ← NIL
Q ← ∅
PUSH(S,s)
while S ≠ ∅ do % while stack S is not empty
u ← POP(S) % remove node on top of stack
for each node v ∈ Adj[u] do % check all neighbors of u
if color[v] = WHITE then
color[v] ← GRAY, d[v] ← d[u] + 1, parent[v] ← u
PUSH(S,v)
color[u] ← BLACK % node u is expanded
35

Depth-first search – example



let the source node be 2 1 7

assume the neighbors are 6
2 8
pushed onto stack by
increasing node labels when 4
5
3
some node is expanded

inicialization:
u color[u] parent[u] d[u]
– all nodes are colored white,
1 w NIL ∞
their distance from source set
2 g NIL 0
to ∞, and pointers to parents 3 w NIL ∞
set to NIL 4 w NIL ∞
– the source node is colored 5 w NIL ∞ 2
gray, assigned distance 0 and 6 w NIL ∞ S
enqueued in Q 7 w NIL ∞
8 w NIL ∞
36

Depth-first search – example



1. iteration: expand node 2* 1 7
6
2 8
5
3 4

u color[u] parent[u] d[u]


1 w NIL ∞
2 g NIL 0
3 w NIL ∞
4 w NIL ∞
5 w NIL ∞ 2
6 w NIL ∞ S
7 w NIL ∞
8 w NIL ∞
37

Depth-first search – example



1. iteration: expand node 2* 1 7
6
2 8
5
3 4

u color[u] parent[u] d[u]


1 g 2 1
2 b NIL 0
8
3 g 2 1
4 w NIL ∞ 3
5 w NIL ∞ 1
6 w NIL ∞ S
7 w NIL ∞
8 g 2 1
38

Depth-first search – example



1. iteration: expand node 2 1 7

2. iteration: expand node 8* 6
2 8
5
3 4

u color[u] parent[u] d[u]


1 g 2 1
2 b NIL 0
8
3 g 2 1
4 w NIL ∞ 3
5 w NIL ∞ 1
6 w NIL ∞ S
7 w NIL ∞
8 g 2 1
39

Depth-first search – example



1. iteration: expand node 2 1 7

2. iteration: expand node 8* 6
2 8
5
3 4

u color[u] parent[u] d[u]


1 g 2 1 7
2 b NIL 0
4
3 g 2 1
4 g 8 2 3
5 w NIL ∞ 1
6 w NIL ∞ S
7 g 8 2
8 b 2 1
40

Depth-first search – example



1. iteration: expand node 2 1 7

2. iteration: expand node 8 6
2 8

3. iteration: expand node 7*
5
3 4

u color[u] parent[u] d[u]


1 g 2 1 7
2 b NIL 0
4
3 g 2 1
4 g 8 2 3
5 w NIL ∞ 1
6 w NIL ∞ S
7 g 8 2
8 b 2 1
41

Depth-first search – example



1. iteration: expand node 2 1 7

2. iteration: expand node 8 6
2 8

3. iteration: expand node 7*
5
3 4

u color[u] parent[u] d[u]


1 g 2 1 6
2 b NIL 0
4
3 g 2 1
4 g 8 2 3
5 w NIL ∞ 1
6 g 7 3 S
7 b 8 2
8 b 2 1
42

Depth-first search – example



1. iteration: expand node 2 1 7

2. iteration: expand node 8 6
2 8

3. iteration: expand node 7
5

4. iteration: expand node 6* 3 4

u color[u] parent[u] d[u]


1 g 2 1 6
2 b NIL 0
4
3 g 2 1
4 g 8 2 3
5 w NIL ∞ 1
6 g 7 3 S
7 b 8 2
8 b 2 1
43

Depth-first search – example



1. iteration: expand node 2 1 7

2. iteration: expand node 8 6
2 8

3. iteration: expand node 7
5

4. iteration: expand node 6* 3 4

u color[u] parent[u] d[u]


1 g 2 1 5
2 b NIL 0
4
3 g 2 1
4 g 8 2 3
5 g 6 4 1
6 b 7 3 S
7 b 8 2
8 b 2 1
44

Depth-first search – example



1. iteration: expand node 2 1 7

2. iteration: expand node 8 6
2 8

3. iteration: expand node 7
5

4. iteration: expand node 6 3 4

5. iteration: expand node 5*
u color[u] parent[u] d[u]
1 g 2 1 5
2 b NIL 0
4
3 g 2 1
4 g 8 2 3
5 g 6 4 1
6 b 7 3 S
7 b 8 2
8 b 2 1
45

Depth-first search – example



1. iteration: expand node 2 1 7

2. iteration: expand node 8 6
2 8

3. iteration: expand node 7
5

4. iteration: expand node 6 3 4

5. iteration: expand node 5*
u color[u] parent[u] d[u]
1 g 2 1
2 b NIL 0
4
3 g 2 1
4 g 8 2 3
5 b 6 4 1
6 b 7 3 S
7 b 8 2
8 b 2 1
46

Depth-first search – example



1. iteration: expand node 2 1 7

2. iteration: expand node 8 6
2 8

3. iteration: expand node 7
5

4. iteration: expand node 6 3 4

5. iteration: expand node 5

6. iteration: expand node 4* u color[u] parent[u] d[u]
1 g 2 1
2 b NIL 0
4
3 g 2 1
4 g 8 2 3
5 b 6 4 1
6 b 7 3 S
7 b 8 2
8 b 2 1
47

Depth-first search – example



1. iteration: expand node 2 1 7

2. iteration: expand node 8 6
2 8

3. iteration: expand node 7
5

4. iteration: expand node 6 3 4

5. iteration: expand node 5

6. iteration: expand node 4* u color[u] parent[u] d[u]
1 g 2 1
2 b NIL 0
3 g 2 1
4 b 8 2 3
5 b 6 4 1
6 b 7 3 S
7 b 8 2
8 b 2 1
48

Depth-first search – example



1. iteration: expand node 2 1 7

2. iteration: expand node 8 6
2 8

3. iteration: expand node 7
5

4. iteration: expand node 6 3 4

5. iteration: expand node 5

6. iteration: expand node 4 u color[u] parent[u] d[u]

7. iteration: expand node 3* 1 g 2 1
2 b NIL 0
3 g 2 1
4 b 8 2 3
5 b 6 4 1
6 b 7 3 S
7 b 8 2
8 b 2 1
49

Depth-first search – example



1. iteration: expand node 2 1 7

2. iteration: expand node 8 6
2 8

3. iteration: expand node 7
5

4. iteration: expand node 6 3 4

5. iteration: expand node 5

6. iteration: expand node 4 u color[u] parent[u] d[u]

7. iteration: expand node 3* 1 g 2 1
2 b NIL 0
3 b 2 1
4 b 8 2
5 b 6 4 1
6 b 7 3 S
7 b 8 2
8 b 2 1
50

Depth-first search – example



1. iteration: expand node 2 1 7

2. iteration: expand node 8 6
2 8

3. iteration: expand node 7
5

4. iteration: expand node 6 3 4

5. iteration: expand node 5

6. iteration: expand node 4 u color[u] parent[u] d[u]

7. iteration: expand node 3 1 g 2 1
2 b NIL 0

8. iteration: expand node 1* 3 b 2 1
4 b 8 2
5 b 6 4 1
6 b 7 3 S
7 b 8 2
8 b 2 1
51

Depth-first search – example



1. iteration: expand node 2 1 7

2. iteration: expand node 8 6
2 8

3. iteration: expand node 7
5

4. iteration: expand node 6 3 4

5. iteration: expand node 5

6. iteration: expand node 4 u color[u] parent[u] d[u]

7. iteration: expand node 3 1 b 2 1
2 b NIL 0

8. iteration: expand node 1* 3 b 2 1
4 b 8 2
5 b 6 4
6 b 7 3 S
7 b 8 2
8 b 2 1
52

Depth-first search – example



the working of DFS can be summarized in a table
iteration expanded node u parent[u] d[u]
1 2 NIL 0
2 8 2 1
3 7 8 2
4 6 7 3
5 5 6 4
6 4 8 2
7 3 2 1
8 1 2 1
53

Depth-first search – example



with the help of pointers to parents we can build the search
tree of DFS
u color[u] parent[u] d[u]
2
1 b 2 1
2 b NIL 0
1 3 8
3 b 2 1
4 b 8 2
7 4 5 b 6 4
6 b 7 3
6 7 b 8 2
8 b 2 1
5
54

Time complexity of BFS and DFS



initialization requires O(|V|) time

inserting and removing one node from a queue requires
O(1) time, for all nodes O(|V|) time

if the graph is described using adjacency lists, the list is
traversed once for each node, but requires O(|E|) time
for all nodes; total time complexity is in this case
T(n) = O(|V| + |E|)

if the graph is described using adjacency matrix, the
algorithm time complexity is T(n) = O(|V|2)

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy