Graph
Graph and its types :
A Graph is a non-linear data structure consisting of nodes and edges .
The nodes are sometimes also referred to as vertices and the edges are
lines and arcs that connect any two nodes in the graph .
A graph can be defined as group of vertices and edges that are used to
connect these vertices. A graph can be seen as a cyclic tree, where the
vertices (Nodes) maintain any complex relationship among them instead
of having parent child relationship.A graph is a non-linear datastructure
consisting of nodes and edges .
Example :
In the above graph , the set of vertices V = {0,1,2,3,4} and the set of
edges E = {01,12,23,34,04,14,13}
Types of Graph:
1. Directed Graph
2. Undirected Graph
Directed Graph:
In a directed graph, edges form an ordered pair. Edges represent a specific path from some vertex A to another
vertex B. Node A is called initial node while node B is called terminal node.
Undirected Graph:
In an undirected graph, edges are not associated with the directions with
them. An undirected graph is shown in the above figure since its edges
are not attached with any of the directions. If an edge exists between
vertex A and B then the vertices can be traversed from B to A as well as
A to B.
Graph Representation :
Graph data structure is represented using following representation :
1. Adjacency Matrix
2. Incidence Matrix
3. Adjacency List
Adjacency Matrix
o Adjacency matrix is a sequential representation.
o It is used to represent which nodes are adjacent to each other. i.e. is there any edge connecting
nodes to a graph.
o In this representation, we have to construct a nXn matrix A. If there is any edge from a vertex i to
vertex j, then the corresponding element of A, ai,j = 1, otherwise ai,j= 0.
o If there is any weighted graph then instead of 1s and 0s, we can store the weight of the edge.
Example
Undirected graph representation
Directed graph represenation
Undirected weighted graph represenation
Adjacency List
o Adjacency list is a linked representation.
o In this representation, for each vertex in the graph, we maintain the list of its neighbors. It means,
every vertex of the graph contains list of its adjacent vertices.
o We have an array of vertices which is indexed by the vertex number and for each vertex v, the
corresponding array element points to a singly linked list of neighbors of v.
Example
Incidence Matrix
In Incidence matrix representation, graph can be represented using a matrix of size:
Total number of vertices by total number of edges.
It means if a graph has 4 vertices and 6 edges, then it can be represented using a matrix of 4X6 class. In this matrix,
columns represent edges and rows represent vertices.
This matrix is filled with either 0 or 1 or -1. Where,
o 0 is used to represent row edge which is not connected to column vertex.
o 1 is used to represent row edge which is connected as outgoing edge to column vertex.
o -1 is used to represent row edge which is connected as incoming edge to column vertex.
Example
Spanning Tree
A spanning tree is a subset of Graph G, such that all the vertices are connected using minimum
possible number of edges. Hence, a spanning tree does not have cycles and a graph may have
more than one spanning tree.
Formula for finding no of spanning tree for paricular graph is :
Minimum Spanning tree - Minimum spanning tree can be defined as the spanning tree in
which the sum of the weights of the edge is minimum. The weight of the spanning tree is
the sum of the weights given to the edges of the spanning tree.
Prim's Algorithm
Prim's Algorithm is a greedy algorithm that is used to find the minimum spanning tree
from a graph. Prim's algorithm finds the subset of edges that includes every vertex of the
graph such that the sum of the weights of the edges can be minimized.
Prim's algorithm starts with the single node and explores all the adjacent nodes with all
the connecting edges at every step. The edges with the minimal weights causing no cycles
in the graph got selected.
The applications of prim's algorithm are -
o Prim's algorithm can be used in network designing.
o It can be used to make network cycles.
o It can also be used to lay down electrical wiring cables.
Cost of MST = 4 + 2 + 1 + 3 = 10 units.
Kruskal's Algorithm is used to find the minimum spanning tree for a connected weighted
graph. The main target of the algorithm is to find the subset of edges by using which we
can traverse every vertex of the graph. It follows the greedy approach that finds an
optimum solution at every stage instead of focusing on a global optimum.
The cost of the MST is = AB + DE + BC + CD = 1 + 2 + 3 + 4 = 10.
Multistage Graph (Shortest Path)
A Multistage graph is a directed, weighted graph in which the nodes can be
divided into a set of stages such that all edges are from a stage to next
stage only (In other words there is no edge between vertices of same stage
and from a vertex of current stage to previous stage).
The vertices of a multistage graph are divided into n number of disjoint
subsets S = { S1 , S2 , S3 ……….. Sn }, where S1 is the source and Sn is the
sink ( destination ). The cardinality of S 1 and Sn are equal to 1. i.e., |S1| =
|Sn| = 1.
We are given a multistage graph, a source and a destination, we need to
find shortest path from source to destination. By convention, we consider
source at stage 1 and destination as last stage.
Following is an example graph we will consider in this article :-
Now there are various strategies we can apply :-
⚫ The Brute force method of finding all possible paths between Source
and Destination and then finding the minimum. That’s the WORST
possible strategy.
⚫ Dijkstra’s Algorithm of Single Source shortest paths. This method will
find shortest paths from source to all other nodes which is not required
in this case. So it will take a lot of time and it doesn’t even use the
SPECIAL feature that this MULTI-STAGE graph has.
⚫ Simple Greedy Method – At each node, choose the shortest outgoing
path. If we apply this approach to the example graph given above we
get the solution as 1 + 4 + 18 = 23. But a quick look at the graph will
show much shorter paths available than 23. So the greedy method fails !
⚫ The best option is Dynamic Programming. So we need to find Optimal
Sub-structure, Recursive Equations and Overlapping Sub-problems.
Bellman Ford Algorithm
Bellman ford algorithm is a single-source shortest path algorithm. This algorithm is used
to find the shortest distance from the single vertex to all the other vertices of a weighted
graph. There are various other algorithms used to find the shortest path like Dijkstra
algorithm, etc. If the weighted graph contains the negative weight values, then the
Dijkstra algorithm does not confirm whether it produces the correct answer or not. In
contrast to Dijkstra algorithm, bellman ford algorithm guarantees the correct answer
even if the weighted graph contains the negative weight values.
Rule of this algorithm
. We will go on relaxing all the edges (n - 1) times where,
. n = number of vertices
Consider the below graph:
As we can observe in the above graph that some of the weights are negative. The above
graph contains 6 vertices so we will go on relaxing till the 5 vertices. Here, we will relax
all the edges 5 times. The loop will iterate 5 times to get the correct answer. If the loop is
iterated more than 5 times then also the answer will be the same, i.e., there would be no
change in the distance between the vertices.
Relaxing means:
. If (d(u) + c(u , v) < d(v))
. d(v) = d(u) + c(u , v)
To find the shortest path of the above graph, the first step is note down all the edges
which are given below:
(A, B), (A, C), (A, D), (B, E), (C, E), (D, C), (D, F), (E, F), (C, B)
Let's consider the source vertex as 'A'; therefore, the distance value at vertex A is 0 and
the distance value at all the other vertices as infinity shown as below:
Since the graph has six vertices so it will have five iterations.
First iteration
Consider the edge (A, B). Denote vertex 'A' as 'u' and vertex 'B' as 'v'. Now use the relaxing
formula:
d(u) = 0
d(v) = ∞
c(u , v) = 6
Since (0 + 6) is less than ∞, so update
. d(v) = d(u) + c(u , v)
d(v) = 0 + 6 = 6
Therefore, the distance of vertex B is 6.
Consider the edge (A, C). Denote vertex 'A' as 'u' and vertex 'C' as 'v'. Now use the relaxing
formula:
d(u) = 0
d(v) = ∞
c(u , v) = 4
Since (0 + 4) is less than ∞, so update
. d(v) = d(u) + c(u , v)
d(v) = 0 + 4 = 4
Therefore, the distance of vertex C is 4.
Consider the edge (A, D). Denote vertex 'A' as 'u' and vertex 'D' as 'v'. Now use the
relaxing formula:
d(u) = 0
d(v) = ∞
c(u , v) = 5
Since (0 + 5) is
less than ∞, so update
. d(v) = d(u) + c(u , v)
d(v) = 0 + 5 = 5
Therefore, the distance of vertex D is 5.
Consider the edge (B, E). Denote vertex 'B' as 'u' and vertex 'E' as 'v'. Now use the relaxing
formula:
d(u) = 6
d(v) = ∞
c(u , v) = -1
Since (6 - 1) is less than ∞, so update
. d(v) = d(u) + c(u , v)
d(v) = 6 - 1= 5
Therefore, the distance of vertex E is 5.
Consider the edge (C, E). Denote vertex 'C' as 'u' and vertex 'E' as 'v'. Now use the relaxing
formula:
d(u) = 4
d(v) = 5
c(u , v) = 3
Since (4 + 3) is greater than 5, so there will be no updation. The value at vertex E is 5.
Consider the edge (D, C). Denote vertex 'D' as 'u' and vertex 'C' as 'v'. Now use the relaxing
formula:
d(u) = 5
d(v) = 4
c(u , v) = -2
Since (5 -2) is less than 4, so update
. d(v) = d(u) + c(u , v)
d(v) = 5 - 2 = 3
Therefore, the distance of vertex C is 3.
Consider the edge (D, F). Denote vertex 'D' as 'u' and vertex 'F' as 'v'. Now use the relaxing
formula:
d(u) = 5
d(v) = ∞
c(u , v) = -1
Since (5 -1) is less than ∞, so update
. d(v) = d(u) + c(u , v)
d(v) = 5 - 1 = 4
Therefore, the distance of vertex F is 4.
Consider the edge (E, F). Denote vertex 'E' as 'u' and vertex 'F' as 'v'. Now use the relaxing
formula:
d(u) = 5
d(v) = ∞
c(u , v) = 3
Since (5 + 3) is greater than 4, so there would be no updation on the distance value of
vertex F.
Consider the edge (C, B). Denote vertex 'C' as 'u' and vertex 'B' as 'v'. Now use the relaxing
formula:
d(u) = 3
d(v) = 6
c(u , v) = -2
Since (3 - 2) is less than 6, so update
. d(v) = d(u) + c(u , v)
d(v) = 3 - 2 = 1
Therefore, the distance of vertex B is 1.
Now the first iteration is completed. We move to the second iteration.
Second iteration:
In the second iteration, we again check all the edges. The first edge is (A, B). Since (0 + 6)
is greater than 1 so there would be no updation in the vertex B.
The next edge is (A, C). Since (0 + 4) is greater than 3 so there would be no updation in
the vertex C.
The next edge is (A, D). Since (0 + 5) equals to 5 so there would be no updation in the
vertex D.
The next edge is (B, E). Since (1 - 1) equals to 0 which is less than 5 so update:
d(v) = d(u) + c(u, v)
d(E) = d(B) +c(B , E)
=1 -1 =0
The next edge is (C, E). Since (3 + 3) equals to 6 which is greater than 5 so there would
be no updation in the vertex E.
The next edge is (D, C). Since (5 - 2) equals to 3 so there would be no updation in the
vertex C.
The next edge is (D, F). Since (5 - 1) equals to 4 so there would be no updation in the
vertex F.
The next edge is (E, F). Since (5 + 3) equals to 8 which is greater than 4 so there would
be no updation in the vertex F.
The next edge is (C, B). Since (3 - 2) equals to 1` so there would be no updation in the
vertex B.
Third iteration
We will perform the same steps as we did in the previous iterations. We will observe that
there will be no updation in the distance of vertices.
. The following are the distances of vertices:
. A: 0
. B: 1
. C: 3
. D: 5
. E: 0
. F: 3
Time Complexity
The time complexity of Bellman ford algorithm would be O(E|V| - 1).
Algorithm :
. function bellmanFord(G, S)
. for each vertex V in G
. distance[V] <- infinite
. previous[V] <- NULL
. distance[S] <- 0
.
. for each vertex V in G
. for each edge (U,V) in G
. tempDistance <- distance[U] + edge_weight(U, V)
. if tempDistance < distance[V]
. distance[V] <- tempDistance
. previous[V] <- U
.
. for each edge (U,V) in G
. If distance[U] + edge_weight(U, V) < distance[V}
. Error: Negative Cycle Exists
.
. return distance[], previous[]
Floyd Warshall Algorithm:
The Floyd Warshall Algorithm is an all pair shortest path
algorithm unlike Dijkstra and Bellman Ford which are single
source shortest path algorithms. This algorithm works for both
the directed and undirected weighted graphs. But, it does not
work for the graphs with negative cycles (where the sum of
the edges in a cycle is negative). It follows Dynamic
Programming approach to check every possible path going via
every possible node in order to calculate shortest distance
between every pair of nodes.
Idea Behind Floyd Warshall Algorithm:
Suppose we have a graph G[][] with V vertices from 1 to N.
Now we have to evaluate a shortestPathMatrix[][] where
shortestPathMatrix[i][j] represents the shortest path between
vertices i and j.
Obviously the shortest path between i to j will have some k
number of intermediate nodes. The idea behind floyd warshall
algorithm is to treat each and every vertex from 1 to N as an
intermediate node one by one.
Floyd Warshall Algorithm Algorithm:
• Initialize the solution matrix same as the input graph matrix as a
first step.
• Then update the solution matrix by considering all vertices as an
intermediate vertex.
• The idea is to pick all vertices one by one and updates all shortest
paths which include the picked vertex as an intermediate vertex in the
shortest path.
• When we pick vertex number k as an intermediate vertex, we
already have considered vertices {0, 1, 2, .. k-1} as intermediate
vertices.
• For every pair (i, j) of the source and destination vertices respectively,
there are two possible cases.
o k is not an intermediate vertex in shortest path from i to j.
We keep the value of dist[i][j] as it is.
o k is an intermediate vertex in shortest path from i to j. We
update the value of dist[i][j] as dist[i][k] + dist[k][j], if dist[i][j] >
dist[i][k] + dist[k][j]
Pseudo-Code of Floyd Warshall Algorithm :
For k = 0 to n – 1
For i = 0 to n – 1
For j = 0 to n – 1
Distance[i, j] = min(Distance[i, j], Distance[i, k] + Distance[k,
j])
where i = source Node, j = Destination Node, k = Intermediate
Node