Graphs
Graphs
Graphs
11 Topological Sorting 94
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
1
Contents
14 Minimize Cash Flow among a given set of friends who have borrowed
money from each other 124
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
16 Assign directions to edges so that the directed graph remains acyclic 140
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
29 Shortest path with exactly k edges in a directed and weighted graph 264
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270
2
Contents
39 Print all Jumping Numbers smaller than or equal to a given value 338
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342
3
Contents
63 Find maximum number of edge disjoint paths between two vertices 544
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 550
4
Contents
67 Union Find Algorithm Set 2 (Union By Rank and Path Compression) 576
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 584
69 Karger’s algorithm for Minimum Cut Set 2 (Analysis and Applications) 593
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 596
5
Contents
84 BFS using vectors & queue as per the algorithm of CLRS 670
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 675
6
Contents
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 774
100 Check if there is a cycle with odd weight sum in an undirected graph 780
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 785
103 Check whether given degrees of vertices represent a Graph or Tree 794
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 796
114 Count nodes within K-distance from all nodes in a set 843
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 846
7
Contents
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 849
118 Count the number of nodes at given level in a tree using BFS. 855
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 859
130 DFS for a n-ary tree (acyclic graph) represented as adjacency list 935
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 938
131 Dial’s Algorithm (Optimized Dijkstra for small range weights) 939
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 950
132 Dijkstra’s Algorithm for Adjacency List Representation Greedy Algo-8 951
8
Contents
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 965
146 Find all reachable nodes from every node present in a given set 1063
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1068
147 Find alphabetical order such that words can be considered sorted 1069
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1073
148 Find if an array of strings can be chained to form a circle Set 1 1074
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1082
9
Contents
149 Find if an array of strings can be chained to form a circle Set 2 1083
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1087
150 Find if there is a path of more than k length from a source 1088
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1092
156 Find the minimum number of moves needed to move from one cell of
matrix to another 1120
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1124
158 Find the number of Islands Set 2 (Using Disjoint Set) 1137
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1141
159 Find the smallest binary digit multiple of given number 1142
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1145
160 Find whether there is path between two cells in matrix 1146
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1151
161 Finding minimum vertex cover size of a graph using binary search 1152
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1157
165 Given a matrix of ’O’ and ’X’, replace ’O’ with ’X’ if surrounded by ’X’ 1179
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1190
10
Contents
179 Java Program for Dijkstra’s Algorithm with Path Printing 1262
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1264
180 k’th heaviest adjacent node in a graph where each vertex has weight 1265
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1267
11
Contents
182 Karger’s algorithm for Minimum Cut Set 1 (Introduction and Imple-
mentation) 1277
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1284
183 Karp’s minimum mean (or average) weight cycle algorithm 1285
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1288
189 Largest subset of Graph vertices with edges of 2 or more colors 1330
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1335
191 Level of Each node in a Tree from source node (using BFS) 1344
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1347
198 Maximum edges that can be added to DAG so that is remains DAG 1384
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1387
12
Contents
202 Minimum cost path from source node to destination node via an in-
termediate node 1400
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1404
203 Minimum Cost Path with Left, Right, Bottom and Up moves allowed 1405
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1408
208 Minimum edges to reverse to make path from a source to a destination 1426
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1431
209 Minimum initial vertices to traverse whole matrix with given conditions 1432
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1435
13
Contents
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1469
220 NetworkX : Python software package for study of complex networks 1488
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1494
224 Number of pair of positions in matrix which are not accessible 1509
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1511
14
Contents
233 Paths to travel each nodes using each edge (Seven Bridges of Königsberg) 1558
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1563
238 Prim’s MST for Adjacency List Representation Greedy Algo-6 1594
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1611
239 Print all paths from a given source to a destination using BFS 1612
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1615
247 Remove all outgoing edges except edge with minimum weight 1668
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1673
15
Contents
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1680
253 Shortest path to reach one prime to other by changing single digit at
a time 1704
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1708
264 Travelling Salesman Problem Set 1 (Naive and Dynamic Programming) 1756
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1757
16
265 Travelling Salesman Problem Set 2 (Approximate using MST) 1758
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1760
266 Two Clique Problem (Check if Graph can be divided in two Cliques) 1761
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1765
267 Undirected graph splitting and its application for number pairs 1766
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1774
272 Word Ladder (Length of shortest chain to reach a target word) 1801
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1805
Contents
17
Chapter 1
18
Chapter 1. Graph and its representations
There are other representations also like, Incidence Matrix and Incidence List. The choice
of the graph representation is situation specific. It totally depends on the type of operations
to be performed and ease of use.
Adjacency Matrix:
Adjacency Matrix is a 2D array of size V x V where V is the number of vertices in a graph.
Let the 2D array be adj[][], a slot adj[i][j] = 1 indicates that there is an edge from vertex i
to vertex j. Adjacency matrix for undirected graph is always symmetric. Adjacency Matrix
is also used to represent weighted graphs. If adj[i][j] = w, then there is an edge from vertex
i to vertex j with weight w.
The adjacency matrix for the above example graph is:
Pros: Representation is easier to implement and follow. Removing an edge takes O(1) time.
Queries like whether there is an edge from vertex ‘u’ to vertex ‘v’ are efficient and can be
done O(1).
Cons: Consumes more space O(V^2). Even if the graph is sparse(contains less number of
19
Chapter 1. Graph and its representations
20
Chapter 1. Graph and its representations
21
Chapter 1. Graph and its representations
22
Chapter 1. Graph and its representations
graph->array[dest].head = newNode;
}
// A utility function to print the adjacency list
// representation of graph
void printGraph(struct Graph* graph)
{
int v;
for (v = 0; v < graph->V; ++v)
{
struct AdjListNode* pCrawl = graph->array[v].head;
printf("\n Adjacency list of vertex %d\n head ", v);
while (pCrawl)
{
printf("-> %d", pCrawl->dest);
pCrawl = pCrawl->next;
}
printf("\n");
}
}
// Driver program to test above functions
int main()
{
// create the graph given in above fugure
int V = 5;
struct Graph* graph = createGraph(V);
addEdge(graph, 0, 1);
addEdge(graph, 0, 4);
addEdge(graph, 1, 2);
addEdge(graph, 1, 3);
addEdge(graph, 1, 4);
addEdge(graph, 2, 3);
addEdge(graph, 3, 4);
// print the adjacency list representation of the above graph
printGraph(graph);
return 0;
}
Java
23
Chapter 1. Graph and its representations
{
// A user define class to represent a graph.
// A graph is an array of adjacency lists.
// Size of array will be V (number of vertices
// in graph)
static class Graph
{
int V;
LinkedList<Integer> adjListArray[];
// constructor
Graph(int V)
{
this.V = V;
// define the size of array as
// number of vertices
adjListArray = new LinkedList[V];
// Create a new list for each vertex
// such that adjacent nodes can be stored
for(int i = 0; i < V ; i++){
adjListArray[i] = new LinkedList<>();
}
}
}
// Adds an edge to an undirected graph
static void addEdge(Graph graph, int src, int dest)
{
// Add an edge from src to dest.
graph.adjListArray[src].addFirst(dest);
// Since graph is undirected, add an edge from dest
// to src also
graph.adjListArray[dest].addFirst(src);
}
// A utility function to print the adjacency list
// representation of graph
static void printGraph(Graph graph)
{
for(int v = 0; v < graph.V; v++)
{
System.out.println("Adjacency list of vertex "+ v);
System.out.print("head");
for(Integer pCrawl: graph.adjListArray[v]){
System.out.print(" -> "+pCrawl);
24
Chapter 1. Graph and its representations
}
System.out.println("\n");
}
}
// Driver program to test above functions
public static void main(String args[])
{
// create the graph given in above figure
int V = 5;
Graph graph = new Graph(V);
addEdge(graph, 0, 1);
addEdge(graph, 0, 4);
addEdge(graph, 1, 2);
addEdge(graph, 1, 3);
addEdge(graph, 1, 4);
addEdge(graph, 2, 3);
addEdge(graph, 3, 4);
// print the adjacency list representation of
// the above graph
printGraph(graph);
}
}
// This code is contributed by Sumit Ghosh
Python3
"""
A Python program to demonstrate the adjacency
list representation of the graph
"""
# A class to represent the adjacency list of the node
class AdjNode:
def __init__(self, data):
self.vertex = data
self.next = None
# A class to represent a graph. A graph
# is the list of the adjacency lists.
# Size of the array will be the no. of the
# vertices "V"
class Graph:
def __init__(self, vertices):
self.V = vertices
self.graph = [None] * self.V
25
Chapter 1. Graph and its representations
# Function to add an edge in an undirected graph
def add_edge(self, src, dest):
# Adding the node to the source node
node = AdjNode(dest)
node.next = self.graph[src]
self.graph[src] = node
# Adding the source node to the destination as
# it is the undirected graph
node = AdjNode(src)
node.next = self.graph[dest]
self.graph[dest] = node
# Function to print the graph
def print_graph(self):
for i in range(self.V):
print("Adjacency list of vertex {}\n head".format(i), end="")
temp = self.graph[i]
while temp:
print(" -> {}".format(temp.vertex), end="")
temp = temp.next
print(" \n")
# Driver program to the above graph class
if __name__ == "__main__":
V = 5
graph = Graph(V)
graph.add_edge(0, 1)
graph.add_edge(0, 4)
graph.add_edge(1, 2)
graph.add_edge(1, 3)
graph.add_edge(1, 4)
graph.add_edge(2, 3)
graph.add_edge(3, 4)
graph.print_graph()
# This code is contributed by Kanav Malhotra
Output:
26
Chapter 1. Graph and its representations
Pros: Saves space O(V+E) . In the worst case, there can be C(V, 2) number of edges in a
graph thus consuming O(V^2) space. Adding a vertex is easier.
Cons: Queries like whether there is an edge from vertex u to vertex v are not efficient and
can be done O(V).
Reference:
http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29
Related Post:
Graph representation using STL for competitive programming Set 1 (DFS of Unweighted
and Undirected)
Graph implementation using STL for competitive programming Set 2 (Weighted graph)
This article is compiled by Aashish Barnwal and reviewed by GeeksforGeeks team. Please
write comments if you find anything incorrect, or you want to share more information about
the topic discussed above.
Improved By : RajatSinghal, kanavMalhotra
Source
https://www.geeksforgeeks.org/graph-and-its-representations/
27
Chapter 2
Following are the implementations of simple Breadth First Traversal from a given source.
The implementation uses adjacency list representation of graphs. STL‘s list container is
used to store lists of adjacent nodes and queue of nodes needed for BFS traversal.
C++
28
Chapter 2. Breadth First Traversal for a Graph
#include<iostream>
#include <list>
using namespace std;
// This class represents a directed graph using
// adjacency list representation
class Graph
{
int V; // No. of vertices
// Pointer to an array containing adjacency
// lists
list<int> *adj;
public:
Graph(int V); // Constructor
// function to add an edge to graph
void addEdge(int v, int w);
// prints BFS traversal from a given source s
void BFS(int s);
};
Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V];
}
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w); // Add w to v’s list.
}
void Graph::BFS(int s)
{
// Mark all the vertices as not visited
bool *visited = new bool[V];
for(int i = 0; i < V; i++)
visited[i] = false;
// Create a queue for BFS
list<int> queue;
// Mark the current node as visited and enqueue it
visited[s] = true;
queue.push_back(s);
29
Chapter 2. Breadth First Traversal for a Graph
// 'i' will be used to get all adjacent
// vertices of a vertex
list<int>::iterator i;
while(!queue.empty())
{
// Dequeue a vertex from queue and print it
s = queue.front();
cout << s << " ";
queue.pop_front();
// Get all adjacent vertices of the dequeued
// vertex s. If a adjacent has not been visited,
// then mark it visited and enqueue it
for (i = adj[s].begin(); i != adj[s].end(); ++i)
{
if (!visited[*i])
{
visited[*i] = true;
queue.push_back(*i);
}
}
}
}
// Driver program to test methods of graph class
int main()
{
// Create a graph given in the above diagram
Graph g(4);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 2);
g.addEdge(2, 0);
g.addEdge(2, 3);
g.addEdge(3, 3);
cout << "Following is Breadth First Traversal "
<< "(starting from vertex 2) \n";
g.BFS(2);
return 0;
}
Java
30
Chapter 2. Breadth First Traversal for a Graph
31
Chapter 2. Breadth First Traversal for a Graph
Python3
32
Chapter 2. Breadth First Traversal for a Graph
33
Chapter 2. Breadth First Traversal for a Graph
print ("Following is Breadth First Traversal"
" (starting from vertex 2)")
g.BFS(2)
# This code is contributed by Neelam Yadav
Output:
Illustration :
34
Chapter 2. Breadth First Traversal for a Graph
35
Chapter 2. Breadth First Traversal for a Graph
Note that the above code traverses only the vertices reachable from a given source vertex.
All the vertices may not be reachable from a given vertex (example Disconnected graph).
To print all the vertices, we can modify the BFS function to do traversal starting from all
nodes one by one (Like the DFS modified version) .
Time Complexity: O(V+E) where V is number of vertices in the graph and E is number of
edges in the graph.
You may like to see below also :
36
Chapter 2. Breadth First Traversal for a Graph
Source
https://www.geeksforgeeks.org/breadth-first-search-or-bfs-for-a-graph/
37
Chapter 3
38
Chapter 3. Applications of Breadth First Traversal
Source
https://www.geeksforgeeks.org/applications-of-breadth-first-traversal/
39
Chapter 4
40
Chapter 4. Depth First Traversal for a Graph
41
Chapter 4. Depth First Traversal for a Graph
list<int>::iterator i;
for (i = adj[v].begin(); i != adj[v].end(); ++i)
if (!visited[*i])
DFSUtil(*i, visited);
}
// DFS traversal of the vertices reachable from v.
// It uses recursive DFSUtil()
void Graph::DFS(int v)
{
// Mark all the vertices as not visited
bool *visited = new bool[V];
for (int i = 0; i < V; i++)
visited[i] = false;
// Call the recursive helper function
// to print DFS traversal
DFSUtil(v, visited);
}
int main()
{
// Create a graph given in the above diagram
Graph g(4);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 2);
g.addEdge(2, 0);
g.addEdge(2, 3);
g.addEdge(3, 3);
cout << "Following is Depth First Traversal"
" (starting from vertex 2) \n";
g.DFS(2);
return 0;
}
Java
42
Chapter 4. Depth First Traversal for a Graph
43
Chapter 4. Depth First Traversal for a Graph
Python
44
Chapter 4. Depth First Traversal for a Graph
Output:
45
Chapter 4. Depth First Traversal for a Graph
46
Chapter 4. Depth First Traversal for a Graph
47
Chapter 4. Depth First Traversal for a Graph
48
Chapter 4. Depth First Traversal for a Graph
void Graph::DFSUtil(int v, bool visited[])
{
// Mark the current node as visited and print it
visited[v] = true;
cout << v << " ";
// Recur for all the vertices adjacent to this vertex
list<int>::iterator i;
for(i = adj[v].begin(); i != adj[v].end(); ++i)
if(!visited[*i])
DFSUtil(*i, visited);
}
// The function to do DFS traversal. It uses recursive DFSUtil()
void Graph::DFS()
{
// Mark all the vertices as not visited
bool *visited = new bool[V];
for (int i = 0; i < V; i++)
visited[i] = false;
// Call the recursive helper function to print DFS traversal
// starting from all vertices one by one
for (int i = 0; i < V; i++)
if (visited[i] == false)
DFSUtil(i, visited);
}
int main()
{
// Create a graph given in the above diagram
Graph g(4);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 2);
g.addEdge(2, 0);
g.addEdge(2, 3);
g.addEdge(3, 3);
cout << "Following is Depth First Traversaln";
g.DFS();
return 0;
}
Java
49
Chapter 4. Depth First Traversal for a Graph
50
Chapter 4. Depth First Traversal for a Graph
Python
51
Chapter 4. Depth First Traversal for a Graph
Output:
52
Chapter 4. Depth First Traversal for a Graph
0 1 2 3
Time Complexity: O(V+E) where V is number of vertices in the graph and E is number of
edges in the graph.
• Applications of DFS.
• Breadth First Traversal for a Graph
• Recent Articles on DFS
Source
https://www.geeksforgeeks.org/depth-first-search-or-dfs-for-a-graph/
53
Chapter 5
54
Chapter 5. Applications of Depth First Search
7) Solving puzzles with only one solution, such as mazes. (DFS can be adapted
to find all solutions to a maze by only including nodes on the current path in the visited set.)
Sources:
http://www8.cs.umu.se/kurser/TDBAfl/VT06/algorithms/LEC/LECTUR16/NODE16.
HTM
http://en.wikipedia.org/wiki/Depth-first_search
http://www.personal.kent.edu/~rmuhamma/Algorithms/MyAlgorithms/GraphAlgor/
depthSearch.htm
http://ww3.algorithmdesign.net/handouts/DFS.pdf
Improved By : JunyiYe
Source
https://www.geeksforgeeks.org/applications-of-depth-first-search/
55
Chapter 6
56
Chapter 6. Iterative Depth First Traversal of Graph
57
Chapter 6. Iterative Depth First Traversal of Graph
Java
58
Chapter 6. Iterative Depth First Traversal of Graph
59
Chapter 6. Iterative Depth First Traversal of Graph
}
// Get all adjacent vertices of the popped vertex s
// If a adjacent has not been visited, then puah it
// to the stack.
Iterator<Integer> itr = adj[s].iterator();
while (itr.hasNext())
{
int v = itr.next();
if(!visited.get(v))
stack.push(v);
}
}
}
}
// Driver program to test methods of graph class
public static void main(String[] args)
{
// Total 5 vertices in graph
Graph g = new Graph(5);
g.addEdge(1, 0);
g.addEdge(0, 2);
g.addEdge(2, 1);
g.addEdge(0, 3);
g.addEdge(1, 4);
System.out.println("Following is the Depth First Traversal");
g.DFS(0);
}
}
Output:
Note that the above implementation prints only vertices that are reachable from a given
vertex. For example, if we remove edges 0-3 and 0-2, the above program would only print 0.
To print all vertices of a graph, we need to call DFS for every vertex. Below is implementation
for the same.
C++
60
Chapter 6. Iterative Depth First Traversal of Graph
61
Chapter 6. Iterative Depth First Traversal of Graph
Java
62
Chapter 6. Iterative Depth First Traversal of Graph
import java.util.*;
public class GFG
{
// This class represents a directed graph using adjacency
// list representation
static class Graph
{
int V; //Number of Vertices
LinkedList<Integer>[] adj; // adjacency lists
//Constructor
Graph(int V)
{
this.V = V;
adj = new LinkedList[V];
for (int i = 0; i < adj.length; i++)
adj[i] = new LinkedList<Integer>();
}
//To add an edge to graph
void addEdge(int v, int w)
{
adj[v].add(w); // Add w to v’s list.
}
// prints all not yet visited vertices reachable from s
void DFSUtil(int s, Vector<Boolean> visited)
{
// Create a stack for DFS
Stack<Integer> stack = new Stack<>();
// Push the current source node
stack.push(s);
while(stack.empty() == false)
{
// Pop a vertex from stack and print it
s = stack.peek();
stack.pop();
// Stack may contain same vertex twice. So
// we need to print the popped item only
// if it is not visited.
63
Chapter 6. Iterative Depth First Traversal of Graph
if(visited.get(s) == false)
{
System.out.print(s + " ");
visited.set(s, true);
}
// Get all adjacent vertices of the popped vertex s
// If a adjacent has not been visited, then puah it
// to the stack.
Iterator<Integer> itr = adj[s].iterator();
while (itr.hasNext())
{
int v = itr.next();
if(!visited.get(v))
stack.push(v);
}
}
}
// prints all vertices in DFS manner
void DFS()
{
Vector<Boolean> visited = new Vector<Boolean>(V);
// Mark all the vertices as not visited
for (int i = 0; i < V; i++)
visited.add(false);
for (int i = 0; i < V; i++)
if (!visited.get(i))
DFSUtil(i, visited);
}
}
// Driver program to test methods of graph class
public static void main(String[] args)
{
Graph g = new Graph(5);
g.addEdge(1, 0);
g.addEdge(2, 1);
g.addEdge(3, 4);
g.addEdge(4, 0);
System.out.println("Following is Depth First Traversal");
g.DFS();
}
}
64
Chapter 6. Iterative Depth First Traversal of Graph
Output:
Source
https://www.geeksforgeeks.org/iterative-depth-first-traversal/
65
Chapter 7
For a disconnected graph, we get the DFS forest as output. To detect cycle, we can check
for a cycle in individual trees by checking back edges.
To detect a back edge, we can keep track of vertices currently in recursion stack of function
for DFS traversal. If we reach a vertex that is already in the recursion stack, then there
is a cycle in the tree. The edge that connects current vertex to the vertex in the recursion
66
Chapter 7. Detect Cycle in a Directed Graph
stack is a back edge. We have used recStack[] array to keep track of vertices in the recursion
stack.
C++
67
Chapter 7. Detect Cycle in a Directed Graph
else if (recStack[*i])
return true;
}
}
recStack[v] = false; // remove the vertex from recursion stack
return false;
}
// Returns true if the graph contains a cycle, else false.
// This function is a variation of DFS() in https://www.geeksforgeeks.org/archives/18212
bool Graph::isCyclic()
{
// Mark all the vertices as not visited and not part of recursion
// stack
bool *visited = new bool[V];
bool *recStack = new bool[V];
for(int i = 0; i < V; i++)
{
visited[i] = false;
recStack[i] = false;
}
// Call the recursive helper function to detect cycle in different
// DFS trees
for(int i = 0; i < V; i++)
if (isCyclicUtil(i, visited, recStack))
return true;
return false;
}
int main()
{
// Create a graph given in the above diagram
Graph g(4);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 2);
g.addEdge(2, 0);
g.addEdge(2, 3);
g.addEdge(3, 3);
if(g.isCyclic())
cout << "Graph contains cycle";
else
cout << "Graph doesn't contain cycle";
return 0;
68
Chapter 7. Detect Cycle in a Directed Graph
Java
69
Chapter 7. Detect Cycle in a Directed Graph
return false;
}
private void addEdge(int source, int dest) {
adj.get(source).add(dest);
}
// Returns true if the graph contains a
// cycle, else false.
// This function is a variation of DFS() in
// https://www.geeksforgeeks.org/archives/18212
private boolean isCyclic()
{
// Mark all the vertices as not visited and
// not part of recursion stack
boolean[] visited = new boolean[V];
boolean[] recStack = new boolean[V];
// Call the recursive helper function to
// detect cycle in different DFS trees
for (int i = 0; i < V; i++)
if (isCyclicUtil(i, visited, recStack))
return true;
return false;
}
// Driver code
public static void main(String[] args)
{
Graph graph = new Graph(4);
graph.addEdge(0, 1);
graph.addEdge(0, 2);
graph.addEdge(1, 2);
graph.addEdge(2, 0);
graph.addEdge(2, 3);
graph.addEdge(3, 3);
if(graph.isCyclic())
System.out.println("Graph contains cycle");
else
System.out.println("Graph doesn't "
+ "contain cycle");
}
}
70
Chapter 7. Detect Cycle in a Directed Graph
Python
71
Chapter 7. Detect Cycle in a Directed Graph
g = Graph(4)
g.addEdge(0, 1)
g.addEdge(0, 2)
g.addEdge(1, 2)
g.addEdge(2, 0)
g.addEdge(2, 3)
g.addEdge(3, 3)
if g.isCyclic() == 1:
print "Graph has a cycle"
else:
print "Graph has no cycle"
# Thanks to Divyanshu Mehta for contributing this code
Output:
Time Complexity of this method is same as time complexity of DFS traversal which is
O(V+E).
In the below article, another O(V + E) method is discussed :
Detect Cycle in a direct graph using colors
Improved By : SagarShah1
Source
https://www.geeksforgeeks.org/detect-cycle-in-a-graph/
72
Chapter 8
Disjoint Set (Or Union-Find) Set 1 (Detect Cycle in an Undirected Graph) - GeeksforGeeks
A disjoint-set data structure is a data structure that keeps track of a set of elements par-
titioned into a number of disjoint (non-overlapping) subsets. A union-find algorithm is an
algorithm that performs two useful operations on such a data structure:
Find: Determine which subset a particular element is in. This can be used for determining
if two elements are in the same subset.
Union: Join two subsets into a single subset.
In this post, we will discuss an application of Disjoint Set Data Structure. The application
is to check whether a given graph contains a cycle or not.
Union-Find Algorithm can be used to check whether an undirected graph contains cycle or
not. Note that we have discussed an algorithm to detect cycle. This is another method
based on Union-Find. This method assumes that graph doesn’t contain any self-loops.
We can keeps track of the subsets in a 1D array, lets call it parent[].
Let us consider the following graph:
73
Chapter 8. Union Find - (Detect Cycle in an Undirected Graph)
For each edge, make subsets using both the vertices of the edge. If both the vertices are in
the same subset, a cycle is found.
Initially, all slots of parent array are initialized to -1 (means there is only one item in every
subset).
0 1 2
-1 -1 -1
Edge 0-2: 0 is in subset 2 and 2 is also in subset 2. Hence, including this edge forms a cycle.
How subset of 0 is same as 2?
0->1->2 // 1 is parent of 0 and 2 is parent of 1
Based on the above explanation, below are implementations:
C/C++
74
Chapter 8. Union Find - (Detect Cycle in an Undirected Graph)
75
Chapter 8. Union Find - (Detect Cycle in an Undirected Graph)
// Iterate through all edges of graph, find subset of both
// vertices of every edge, if both subsets are same, then
// there is cycle in graph.
for(int i = 0; i < graph->E; ++i)
{
int x = find(parent, graph->edge[i].src);
int y = find(parent, graph->edge[i].dest);
if (x == y)
return 1;
Union(parent, x, y);
}
return 0;
}
// Driver program to test above functions
int main()
{
/* Let us create following graph
0
| \
| \
1-----2 */
int V = 3, E = 3;
struct Graph* graph = createGraph(V, E);
// add edge 0-1
graph->edge[0].src = 0;
graph->edge[0].dest = 1;
// add edge 1-2
graph->edge[1].src = 1;
graph->edge[1].dest = 2;
// add edge 0-2
graph->edge[2].src = 0;
graph->edge[2].dest = 2;
if (isCycle(graph))
printf( "graph contains cycle" );
else
printf( "graph doesn't contain cycle" );
return 0;
}
76
Chapter 8. Union Find - (Detect Cycle in an Undirected Graph)
Java
77
Chapter 8. Union Find - (Detect Cycle in an Undirected Graph)
78
Chapter 8. Union Find - (Detect Cycle in an Undirected Graph)
else
System.out.println( "graph doesn't contain cycle" );
}
}
Python
79
Chapter 8. Union Find - (Detect Cycle in an Undirected Graph)
Output:
Note that the implementation of union() and find() is naive and takes O(n) time in worst
case. These methods can be improved to O(Logn) using Union by Rank or Height. We will
soon be discussing Union by Rank in a separate post.
Related Articles :
Union-Find Algorithm Set 2 (Union By Rank and Path Compression)
Disjoint Set Data Structures (Java Implementation)
Greedy Algorithms Set 2 (Kruskal’s Minimum Spanning Tree Algorithm)
Job Sequencing Problem Set 2 (Using Disjoint Set)
This article is compiled by Aashish Barnwal and reviewed by GeeksforGeeks team. Please
write comments if you find anything incorrect, or you want to share more information about
the topic discussed above.
Improved By : avinashr175
Source
https://www.geeksforgeeks.org/union-find/
80
Chapter 9
We have discussed cycle detection for directed graph. We have also discussed a union-find
algorithm for cycle detection in undirected graphs. The time complexity of the union-find
algorithm is O(ELogV). Like directed graphs, we can use DFSto detect cycle in an undirected
graph in O(V+E) time. We do a DFS traversal of the given graph. For every visited vertex
‘v’, if there is an adjacent ‘u’ such that u is already visited and u is not parent of v, then
there is a cycle in graph. If we don’t find such an adjacent for any vertex, we say that there
is no cycle. The assumption of this approach is that there are no parallel edges between any
two vertices.
C++
81
Chapter 9. Detect cycle in an Undirected graph
82
Chapter 9. Detect cycle in an Undirected graph
}
return false;
}
// Returns true if the graph contains a cycle, else false.
bool Graph::isCyclic()
{
// Mark all the vertices as not visited and not part of recursion
// stack
bool *visited = new bool[V];
for (int i = 0; i < V; i++)
visited[i] = false;
// Call the recursive helper function to detect cycle in different
// DFS trees
for (int u = 0; u < V; u++)
if (!visited[u]) // Don't recur for u if it is already visited
if (isCyclicUtil(u, visited, -1))
return true;
return false;
}
// Driver program to test above functions
int main()
{
Graph g1(5);
g1.addEdge(1, 0);
g1.addEdge(0, 2);
g1.addEdge(2, 0);
g1.addEdge(0, 3);
g1.addEdge(3, 4);
g1.isCyclic()? cout << "Graph contains cycle\n":
cout << "Graph doesn't contain cycle\n";
Graph g2(3);
g2.addEdge(0, 1);
g2.addEdge(1, 2);
g2.isCyclic()? cout << "Graph contains cycle\n":
cout << "Graph doesn't contain cycle\n";
return 0;
}
Java
83
Chapter 9. Detect cycle in an Undirected graph
import java.util.*;
// This class represents a directed graph using adjacency list
// representation
class Graph
{
private int V; // No. of vertices
private LinkedList<Integer> adj[]; // Adjacency List Represntation
// Constructor
Graph(int v) {
V = v;
adj = new LinkedList[v];
for(int i=0; i<v; ++i)
adj[i] = new LinkedList();
}
// Function to add an edge into the graph
void addEdge(int v,int w) {
adj[v].add(w);
adj[w].add(v);
}
// A recursive function that uses visited[] and parent to detect
// cycle in subgraph reachable from vertex v.
Boolean isCyclicUtil(int v, Boolean visited[], int parent)
{
// Mark the current node as visited
visited[v] = true;
Integer i;
// Recur for all the vertices adjacent to this vertex
Iterator<Integer> it = adj[v].iterator();
while (it.hasNext())
{
i = it.next();
// If an adjacent is not visited, then recur for that
// adjacent
if (!visited[i])
{
if (isCyclicUtil(i, visited, v))
return true;
}
// If an adjacent is visited and not parent of current
// vertex, then there is a cycle.
else if (i != parent)
84
Chapter 9. Detect cycle in an Undirected graph
return true;
}
return false;
}
// Returns true if the graph contains a cycle, else false.
Boolean isCyclic()
{
// Mark all the vertices as not visited and not part of
// recursion stack
Boolean visited[] = new Boolean[V];
for (int i = 0; i < V; i++)
visited[i] = false;
// Call the recursive helper function to detect cycle in
// different DFS trees
for (int u = 0; u < V; u++)
if (!visited[u]) // Don't recur for u if already visited
if (isCyclicUtil(u, visited, -1))
return true;
return false;
}
// Driver method to test above methods
public static void main(String args[])
{
// Create a graph given in the above diagram
Graph g1 = new Graph(5);
g1.addEdge(1, 0);
g1.addEdge(0, 2);
g1.addEdge(2, 0);
g1.addEdge(0, 3);
g1.addEdge(3, 4);
if (g1.isCyclic())
System.out.println("Graph contains cycle");
else
System.out.println("Graph doesn't contains cycle");
Graph g2 = new Graph(3);
g2.addEdge(0, 1);
g2.addEdge(1, 2);
if (g2.isCyclic())
System.out.println("Graph contains cycle");
else
System.out.println("Graph doesn't contains cycle");
}
85
Chapter 9. Detect cycle in an Undirected graph
}
// This code is contributed by Aakash Hasija
Python
86
Chapter 9. Detect cycle in an Undirected graph
#DFS trees
for i in range(self.V):
if visited[i] ==False: #Don't recur for u if it is already visited
if(self.isCyclicUtil(i,visited,-1))== True:
return True
return False
# Create a graph given in the above diagram
g = Graph(5)
g.addEdge(1, 0)
g.addEdge(0, 2)
g.addEdge(2, 0)
g.addEdge(0, 3)
g.addEdge(3, 4)
if g.isCyclic():
print "Graph contains cycle"
else :
print "Graph does not contain cycle "
g1 = Graph(3)
g1.addEdge(0,1)
g1.addEdge(1,2)
if g1.isCyclic():
print "Graph contains cycle"
else :
print "Graph does not contain cycle "
#This code is contributed by Neelam Yadav
Output:
Time Complexity: The program does a simple DFS Traversal of graph and graph is
represented using adjacency list. So the time complexity is O(V+E)
Exercise: Can we use BFS to detect cycle in an undirected graph in O(V+E) time? What
about directed graphs?
Source
https://www.geeksforgeeks.org/detect-cycle-undirected-graph/
87
Chapter 10
88
Chapter 10. Longest Path in a Directed Acyclic Graph
89
Chapter 10. Longest Path in a Directed Acyclic Graph
#include <list>
#include <stack>
#define NINF INT_MIN
using namespace std;
// Graph is represented using adjacency list. Every
// node of adjacency list contains vertex number of
// the vertex to which edge connects. It also
// contains weight of the edge
class AdjListNode {
int v;
int weight;
public:
AdjListNode(int _v, int _w)
{
v = _v;
weight = _w;
}
int getV() { return v; }
int getWeight() { return weight; }
};
// Class to represent a graph using adjacency list
// representation
class Graph {
int V; // No. of vertices'
// Pointer to an array containing adjacency lists
list<AdjListNode>* adj;
// A function used by longestPath
void topologicalSortUtil(int v, bool visited[],
stack<int>& Stack);
public:
Graph(int V); // Constructor
// function to add an edge to graph
void addEdge(int u, int v, int weight);
// Finds longest distances from given source vertex
void longestPath(int s);
};
Graph::Graph(int V) // Constructor
{
this->V = V;
90
Chapter 10. Longest Path in a Directed Acyclic Graph
91
Chapter 10. Longest Path in a Directed Acyclic Graph
92
Chapter 10. Longest Path in a Directed Acyclic Graph
Output:
Time Complexity: Time complexity of topological sorting is O(V+E). After finding topo-
logical order, the algorithm process all vertices and for every vertex, it runs a loop for all
adjacent vertices. Total adjacent vertices in a graph is O(E). So the inner loop runs O(V+E)
times. Therefore, overall time complexity of this algorithm is O(V+E).
Exercise: The above solution print longest distances, extend the code to print paths also.
Micro Focus
Improved By : Rohit0803, pranith maddineni
Source
https://www.geeksforgeeks.org/find-longest-path-directed-acyclic-graph/
93
Chapter 11
Topological Sorting
94
Chapter 11. Topological Sorting
We recommend to first see implementation of DFS here. We can modify DFSto find Topolog-
ical Sorting of a graph. In DFS, we start from a vertex, we first print it and then recursively
call DFS for its adjacent vertices. In topological sorting, we use a temporary stack. We
don’t print the vertex immediately, we first recursively call topological sorting for all its
adjacent vertices, then push it to a stack. Finally, print contents of stack. Note that a
vertex is pushed to stack only when all of its adjacent vertices (and their adjacent vertices
and so on) are already in stack.
Following are the implementations of topological sorting. Please see the code for Depth
First Traversal for a disconnected Graph and note the differences between the second code
given there and the below code.
C++
95
Chapter 11. Topological Sorting
}
// A recursive function used by topologicalSort
void Graph::topologicalSortUtil(int v, bool visited[],
stack<int> &Stack)
{
// Mark the current node as visited.
visited[v] = true;
// Recur for all the vertices adjacent to this vertex
list<int>::iterator i;
for (i = adj[v].begin(); i != adj[v].end(); ++i)
if (!visited[*i])
topologicalSortUtil(*i, visited, Stack);
// Push current vertex to stack which stores result
Stack.push(v);
}
// The function to do Topological Sort. It uses recursive
// topologicalSortUtil()
void Graph::topologicalSort()
{
stack<int> Stack;
// Mark all the vertices as not visited
bool *visited = new bool[V];
for (int i = 0; i < V; i++)
visited[i] = false;
// Call the recursive helper function to store Topological
// Sort starting from all vertices one by one
for (int i = 0; i < V; i++)
if (visited[i] == false)
topologicalSortUtil(i, visited, Stack);
// Print contents of stack
while (Stack.empty() == false)
{
cout << Stack.top() << " ";
Stack.pop();
}
}
// Driver program to test above functions
int main()
{
// Create a graph given in the above diagram
96
Chapter 11. Topological Sorting
Graph g(6);
g.addEdge(5, 2);
g.addEdge(5, 0);
g.addEdge(4, 0);
g.addEdge(4, 1);
g.addEdge(2, 3);
g.addEdge(3, 1);
cout << "Following is a Topological Sort of the given graph \n";
g.topologicalSort();
return 0;
}
Java
97
Chapter 11. Topological Sorting
// vertex
Iterator<Integer> it = adj[v].iterator();
while (it.hasNext())
{
i = it.next();
if (!visited[i])
topologicalSortUtil(i, visited, stack);
}
// Push current vertex to stack which stores result
stack.push(new Integer(v));
}
// The function to do Topological Sort. It uses
// recursive topologicalSortUtil()
void topologicalSort()
{
Stack stack = new Stack();
// Mark all the vertices as not visited
boolean visited[] = new boolean[V];
for (int i = 0; i < V; i++)
visited[i] = false;
// Call the recursive helper function to store
// Topological Sort starting from all vertices
// one by one
for (int i = 0; i < V; i++)
if (visited[i] == false)
topologicalSortUtil(i, visited, stack);
// Print contents of stack
while (stack.empty()==false)
System.out.print(stack.pop() + " ");
}
// Driver method
public static void main(String args[])
{
// Create a graph given in the above diagram
Graph g = new Graph(6);
g.addEdge(5, 2);
g.addEdge(5, 0);
g.addEdge(4, 0);
g.addEdge(4, 1);
g.addEdge(2, 3);
g.addEdge(3, 1);
98
Chapter 11. Topological Sorting
Python
99
Chapter 11. Topological Sorting
# Print contents of the stack
print stack
g= Graph(6)
g.addEdge(5, 2);
g.addEdge(5, 0);
g.addEdge(4, 0);
g.addEdge(4, 1);
g.addEdge(2, 3);
g.addEdge(3, 1);
print "Following is a Topological Sort of the given graph"
g.topologicalSort()
#This code is contributed by Neelam Yadav
Output:
Time Complexity: The above algorithm is simply DFS with an extra stack. So time
complexity is same as DFS which is O(V+E).
Applications:
Topological Sorting is mainly used for scheduling jobs from the given dependencies among
jobs. In computer science, applications of this type arise in instruction scheduling, ordering
of formula cell evaluation when recomputing formula values in spreadsheets, logic synthesis,
determining the order of compilation tasks to perform in makefiles, data serialization, and
resolving symbol dependencies in linkers [2].
Related Articles:
Kahn’s algorithm for Topological Sorting : Another O(V + E) algorithm.
All Topological Sorts of a Directed Acyclic Graph
References:
http://www.personal.kent.edu/~rmuhamma/Algorithms/MyAlgorithms/GraphAlgor/
topoSort.htm
http://en.wikipedia.org/wiki/Topological_sorting
Improved By : ConstantineShulyupin
Source
https://www.geeksforgeeks.org/topological-sorting/
100
Chapter 12
A bipartite graph is possible if the graph coloring is possible using two colors such that
vertices in a set are colored with the same color. Note that it is possible to color a cycle
graph with even cycle using two colors. For example, see the following graph.
101
Chapter 12. Check whether a given graph is Bipartite or not
It is not possible to color a cycle graph with odd cycle using two colors.
102
Chapter 12. Check whether a given graph is Bipartite or not
103
Chapter 12. Check whether a given graph is Bipartite or not
while (!q.empty())
{
// Dequeue a vertex from queue ( Refer http://goo.gl/35oz8 )
int u = q.front();
q.pop();
// Return false if there is a self-loop
if (G[u][u] == 1)
return false;
// Find all non-colored adjacent vertices
for (int v = 0; v < V; ++v)
{
// An edge from u to v exists and
// destination v is not colored
if (G[u][v] && colorArr[v] == -1)
{
// Assign alternate color to this adjacent v of u
colorArr[v] = 1 - colorArr[u];
q.push(v);
}
// An edge from u to v exists and destination
// v is colored with same color as u
else if (G[u][v] && colorArr[v] == colorArr[u])
return false;
}
}
// If we reach here, then all adjacent
// vertices can be colored with alternate color
return true;
}
// Driver program to test above function
int main()
{
int G[][V] = {{0, 1, 0, 1},
{1, 0, 1, 0},
{0, 1, 0, 1},
{1, 0, 1, 0}
};
isBipartite(G, 0) ? cout << "Yes" : cout << "No";
return 0;
}
Java
104
Chapter 12. Check whether a given graph is Bipartite or not
105
Chapter 12. Check whether a given graph is Bipartite or not
{
// An edge from u to v exists
// and destination v is not colored
if (G[u][v]==1 && colorArr[v]==-1)
{
// Assign alternate color to this adjacent v of u
colorArr[v] = 1-colorArr[u];
q.add(v);
}
// An edge from u to v exists and destination
// v is colored with same color as u
else if (G[u][v]==1 && colorArr[v]==colorArr[u])
return false;
}
}
// If we reach here, then all adjacent vertices can
// be colored with alternate color
return true;
}
// Driver program to test above function
public static void main (String[] args)
{
int G[][] = {{0, 1, 0, 1},
{1, 0, 1, 0},
{0, 1, 0, 1},
{1, 0, 1, 0}
};
Bipartite b = new Bipartite();
if (b.isBipartite(G, 0))
System.out.println("Yes");
else
System.out.println("No");
}
}
// Contributed by Aakash Hasija
Python
106
Chapter 12. Check whether a given graph is Bipartite or not
107
Chapter 12. Check whether a given graph is Bipartite or not
Output:
Yes
The above algorithm works only if the graph is strongly connected. In above code, we always
start with source 0 and assume that vertices are visited from it. One important observation
is a graph with no edges is also Bipiartite. Note that the Bipartite condition says all edges
should be from one set to another.
We can extend the above code to handle cases when a graph is not connected. The idea is
repeatedly call above method for all not yet visited vertices.
C++
108
Chapter 12. Check whether a given graph is Bipartite or not
109
Chapter 12. Check whether a given graph is Bipartite or not
Java
110
Chapter 12. Check whether a given graph is Bipartite or not
111
Chapter 12. Check whether a given graph is Bipartite or not
Output:
Yes
Time Complexity of the above approach is same as that Breadth First Search. In above
implementation is O(V^2) where V is number of vertices. If graph is represented using
adjacency list, then the complexity becomes O(V+E).
Exercise:
1. Can DFS algorithm be used to check the bipartite-ness of a graph? If yes, how?
Solution :
112
Chapter 12. Check whether a given graph is Bipartite or not
// Using recursion.
#include <iostream>
using namespace std;
#define V 4
bool colorGraph(int G[][V],int color[],int pos, int c){
if(color[pos] != -1 && color[pos] !=c)
return false;
// color this pos as c and all its neighbours and 1-c
color[pos] = c;
bool ans = true;
for(int i=0;i<V;i++){
if(G[pos][i]){
if(color[i] == -1)
ans &= colorGraph(G,color,i,1-c);
if(color[i] !=-1 && color[i] != 1-c)
return false;
}
if (!ans)
return false;
}
return true;
}
bool isBipartite(int G[][V]){
int color[V];
for(int i=0;i<V;i++)
color[i] = -1;
//start is vertex 0;
int pos = 0;
// two colors 1 and 0
return colorGraph(G,color,pos,1);
}
int main()
{
int G[][V] = {{0, 1, 0, 1},
{1, 0, 1, 0},
{0, 1, 0, 1},
{1, 0, 1, 0}
113
Chapter 12. Check whether a given graph is Bipartite or not
};
isBipartite(G) ? cout<< "Yes" : cout << "No";
return 0;
}
// This code is contributed By Mudit Verma
References:
http://en.wikipedia.org/wiki/Graph_coloring
http://en.wikipedia.org/wiki/Bipartite_graph
This article is compiled by Aashish Barnwal. Please write comments if you find anything
incorrect, or you want to share more information about the topic discussed above
Improved By : Mudit Verma
Source
https://www.geeksforgeeks.org/bipartite-graph/
114
Chapter 13
115
Chapter 13. Snake and Ladder Problem
For example, consider the board shown, the minimum number of dice throws required to
reach cell 30 from cell 1 is 3.
Following are the steps:
a) First throw two on dice to reach cell number 3 and then ladder to reach 22
b) Then throw 6 to reach 28.
c) Finally through 2 to reach 30.
There can be other solutions as well like (2, 2, 6), (2, 4, 4), (2, 3, 5).. etc.
The idea is to consider the given snake and ladder board as a directed graph with number
of vertices equal to the number of cells in the board. The problem reduces to finding the
shortest path in a graph. Every vertex of the graph has an edge to next six vertices if next 6
vertices do not have a snake or ladder. If any of the next six vertices has a snake or ladder,
then the edge from current vertex goes to the top of the ladder or tail of the snake. Since all
edges are of equal weight, we can efficiently find shortest path using Breadth First Search
of the graph.
Following is the implementation of the above idea. The input is represented by two things,
first is ‘N’ which is number of cells in the given board, second is an array ‘move[0…N-1]’ of
size N. An entry move[i] is -1 if there is no snake and no ladder from i, otherwise move[i]
contains index of destination cell for the snake or the ladder at i.
C++
116
Chapter 13. Snake and Ladder Problem
117
Chapter 13. Snake and Ladder Problem
}
// We reach here when 'qe' has last vertex
// return the distance of vertex in 'qe'
return qe.dist;
}
// Driver program to test methods of graph class
int main()
{
// Let us construct the board given in above diagram
int N = 30;
int moves[N];
for (int i = 0; i<N; i++)
moves[i] = -1;
// Ladders
moves[2] = 21;
moves[4] = 7;
moves[10] = 25;
moves[19] = 28;
// Snakes
moves[26] = 0;
moves[20] = 8;
moves[16] = 3;
moves[18] = 6;
cout << "Min Dice throws required is " << getMinDiceThrows(moves, N);
return 0;
}
Java
118
Chapter 13. Snake and Ladder Problem
}
// This function returns minimum number of dice
// throws required to Reach last cell from 0'th cell
// in a snake and ladder game. move[] is an array of
// size N where N is no. of cells on board If there
// is no snake or ladder from cell i, then move[i]
// is -1 Otherwise move[i] contains cell to which
// snake or ladder at i takes to.
static int getMinDiceThrows(int move[], int n)
{
int visited[] = new int[n];
Queue<qentry> q = new LinkedList<>();
qentry qe = new qentry();
qe.v = 0;
qe.dist = 0;
// Mark the node 0 as visited and enqueue it.
visited[0] = 1;
q.add(qe);
// Do a BFS starting from vertex at index 0
while (!q.isEmpty())
{
qe = q.remove();
int v = qe.v;
// If front vertex is the destination
// vertex, we are done
if (v == n - 1)
break;
// Otherwise dequeue the front vertex and
// enqueue its adjacent vertices (or cell
// numbers reachable through a dice throw)
for (int j = v + 1; j <= (v + 6) && j < n; ++j)
{
// If this cell is already visited, then ignore
if (visited[j] == 0)
{
// Otherwise calculate its distance and
// mark it as visited
qentry a = new qentry();
a.dist = (qe.dist + 1);
visited[j] = 1;
// Check if there a snake or ladder at 'j'
// then tail of snake or top of ladder
119
Chapter 13. Snake and Ladder Problem
Python3
120
Chapter 13. Snake and Ladder Problem
class QueueEntry(object):
def __init__(self, v = 0, dist = 0):
self.v = v
self.dist = dist
'''This function returns minimum number of
dice throws required to. Reach last cell
from 0'th cell in a snake and ladder game.
move[] is an array of size N where N is
no. of cells on board. If there is no
snake or ladder from cell i, then move[i]
is -1. Otherwise move[i] contains cell to
which snake or ladder at i takes to.'''
def getMinDiceThrows(move, N):
# The graph has N vertices. Mark all
# the vertices as not visited
visited = [False] * N
# Create a queue for BFS
queue = []
# Mark the node 0 as visited and enqueue it
visited[0] = True
# Distance of 0't vertex is also 0
# Enqueue 0'th vertex
queue.append(QueueEntry(0, 0))
# Do a BFS starting from vertex at index 0
qe = QueueEntry() # A queue entry (qe)
while queue:
qe = queue.pop(0)
v = qe.v # Vertex no. of queue entry
# If front vertex is the destination
# vertex, we are done
if v == N - 1:
break
# Otherwise dequeue the front vertex
# and enqueue its adjacent vertices
# (or cell numbers reachable through
# a dice throw)
j = v + 1
while j <= v + 6 and j < N:
# If this cell is already visited,
121
Chapter 13. Snake and Ladder Problem
Output:
122
Chapter 13. Snake and Ladder Problem
Time complexity of the above solution is O(N) as every cell is added and removed only once
from queue. And a typical enqueue or dequeue operation takes O(1) time.
This article is contributed by Siddharth. Please write comments if you find anything
incorrect, or you want to share more information about the topic discussed above.
Source
https://www.geeksforgeeks.org/snake-ladder-problem-2/
123
Chapter 14
Minimize Cash Flow among a given set of friends who have borrowed money from each other
- GeeksforGeeks
Given a number of friends who have to give or take some amount of money from one another.
Design an algorithm by which the total cash flow among all the friends is minimized.
Example:
Following diagram shows input debts to be settled.
124
Chapter 14. Minimize Cash Flow among a given set of friends who have borrowed money
from each other
The idea is to use Greedy algorithm where at every step, settle all amounts of one person
and recur for remaining n-1 persons.
How to pick the first person? To pick the first person, calculate the net amount for every
person where net amount is obtained by subtracting all debts (amounts to pay) from all
credits (amounts to be paid). Once net amount for every person is evaluated, find two
persons with maximum and minimum net amounts. These two persons are the most creditors
and debtors. The person with minimum of two is our first person to be settled and removed
from list. Let the minimum of two amounts be x. We pay ‘x’ amount from the maximum
debtor to maximum creditor and settle one person. If x is equal to the maximum debit,
then maximum debtor is settled, else maximum creditor is settled.
The following is detailed algorithm.
Do following for every person Pi where i is from 0 to n-1.
1) Compute the net amount for every person. The net amount for person ‘i’ can be computed
be subtracting sum of all debts from sum of all credits.
2) Find the two persons that are maximum creditor and maximum debtor. Let the maximum
amount to be credited maximum creditor be maxCredit and maximum amount to be debited
from maximum debtor be maxDebit. Let the maximum debtor be Pd and maximum creditor
be Pc.
3) Find the minimum of maxDebit and maxCredit. Let minimum of two be x. Debit ‘x’
from Pd and credit this amount to Pc
4) If x is equal to maxCredit, then remove Pc from set of persons and recur for remaining
(n-1) persons.
5) If x is equal to maxDebit, then remove Pd from set of persons and recur for
remaining (n-1) persons.
Thanks to Balaji S for suggesting this method in a comment here.
The following is implementation of above algorithm.
C++
125
Chapter 14. Minimize Cash Flow among a given set of friends who have borrowed money
from each other
#include<iostream>
using namespace std;
// Number of persons (or vertices in the graph)
#define N 3
// A utility function that returns index of minimum value in arr[]
int getMin(int arr[])
{
int minInd = 0;
for (int i=1; i<N; i++)
if (arr[i] < arr[minInd])
minInd = i;
return minInd;
}
// A utility function that returns index of maximum value in arr[]
int getMax(int arr[])
{
int maxInd = 0;
for (int i=1; i<N; i++)
if (arr[i] > arr[maxInd])
maxInd = i;
return maxInd;
}
// A utility function to return minimum of 2 values
int minOf2(int x, int y)
{
return (x<y)? x: y;
}
// amount[p] indicates the net amount to be credited/debited
// to/from person 'p'
// If amount[p] is positive, then i'th person will amount[i]
// If amount[p] is negative, then i'th person will give -amount[i]
void minCashFlowRec(int amount[])
{
// Find the indexes of minimum and maximum values in amount[]
// amount[mxCredit] indicates the maximum amount to be given
// (or credited) to any person .
// And amount[mxDebit] indicates the maximum amount to be taken
// (or debited) from any person.
// So if there is a positive value in amount[], then there must
// be a negative value
int mxCredit = getMax(amount), mxDebit = getMin(amount);
// If both amounts are 0, then all amounts are settled
126
Chapter 14. Minimize Cash Flow among a given set of friends who have borrowed money
from each other
127
Chapter 14. Minimize Cash Flow among a given set of friends who have borrowed money
from each other
Java
128
Chapter 14. Minimize Cash Flow among a given set of friends who have borrowed money
from each other
129
Chapter 14. Minimize Cash Flow among a given set of friends who have borrowed money
from each other
Python3
130
Chapter 14. Minimize Cash Flow among a given set of friends who have borrowed money
from each other
131
Chapter 14. Minimize Cash Flow among a given set of friends who have borrowed money
from each other
minCashFlowRec(amount)
# Given a set of persons as graph[] where
# graph[i][j] indicates the amount that
# person i needs to pay person j, this
# function finds and prints the minimum
# cash flow to settle all debts.
def minCashFlow(graph):
# Create an array amount[],
# initialize all value in it as 0.
amount = [0 for i in range(N)]
# Calculate the net amount to be paid
# to person 'p', and stores it in amount[p].
# The value of amount[p] can be calculated by
# subtracting debts of 'p' from credits of 'p'
for p in range(N):
for i in range(N):
amount[p] += (graph[i][p] - graph[p][i])
minCashFlowRec(amount)
# Driver code
# graph[i][j] indicates the amount
# that person i needs to pay person j
graph = [ [0, 1000, 2000],
[0, 0, 5000],
[0, 0, 0] ]
minCashFlow(graph)
# This code is contributed by Anant Agarwal.
C#
132
Chapter 14. Minimize Cash Flow among a given set of friends who have borrowed money
from each other
133
Chapter 14. Minimize Cash Flow among a given set of friends who have borrowed money
from each other
134
Chapter 14. Minimize Cash Flow among a given set of friends who have borrowed money
from each other
Output:
Source
https://www.geeksforgeeks.org/minimize-cash-flow-among-given-set-friends-borrowed-money/
135
Chapter 15
136
Chapter 15. Boggle (Find all possible words in a board of characters)
The idea is to consider every character as a starting character and find all words starting
with it. All words starting from a character can be found using Depth First Traversal. We
do depth first traversal starting from every cell. We keep track of visited cells to make sure
that a cell is considered only once in a word.
137
Chapter 15. Boggle (Find all possible words in a board of characters)
138
Chapter 15. Boggle (Find all possible words in a board of characters)
Output:
Note that the above solution may print the same word multiple times. For example, if
we add “SEEK” to the dictionary, it is printed multiple times. To avoid this, we can use
hashing to keep track of all printed words.
In below set 2, we have discussed Trie based optimized solution:
Boggle Set 2 (Using Trie)
This article is contributed by Rishabh. Please write comments if you find anything incor-
rect, or you want to share more information about the topic discussed above.
Source
https://www.geeksforgeeks.org/boggle-find-possible-words-board-characters/
139
Chapter 16
Assign directions to edges so that the directed graph remains acyclic - GeeksforGeeks
Given a graph with both directed and undirected edges. It is given that the directed edges
don’t form cycle. How to assign directions to undirected edges so that the graph (with all
directed edges) remains acyclic even after the assignment?
For example, in the below graph, blue edges don’t have directions.
We strongly recommend to minimize your browser and try this yourself first.
140
Chapter 16. Assign directions to edges so that the directed graph remains acyclic
The idea is to use Topological Sorting. Following are two steps used in the algorithm.
1) Consider the subgraph with directed edges only and find topological sorting of the sub-
graph. In the above example, topological sorting is {0, 5, 1, 2, 3, 4}. Below diagram shows
topological sorting for the above example graph.
2) Use above topological sorting to assign directions to undirected edges. For every undi-
rected edge (u, v), assign it direction from u to v if u comes before v in topological sorting,
else assign it direction from v to u.
Below diagram shows assigned directions in the example graph.
Source: http://courses.csail.mit.edu/6.006/oldquizzes/solutions/q2-f2009-sol.pdf
This article is contributed by Aditya Agrawal. Please write comments if you find anything
incorrect, or you want to share more information about the topic discussed above.
Source
https://www.geeksforgeeks.org/assign-directions-to-edges-so-that-the-directed-graph-remains-acyclic/
141
Chapter 17
142
Chapter 17. Prim’s Minimum Spanning Tree (MST))
are used only for vertices which are not yet included in MST, the key value for these vertices
indicate the minimum weight edges connecting them to the set of vertices included in MST.
Let us understand with the following example:
The set mstSet is initially empty and keys assigned to vertices are {0, INF, INF, INF, INF,
INF, INF, INF} where INF indicates infinite. Now pick the vertex with minimum key value.
The vertex 0 is picked, include it in mstSet. So mstSet becomes {0}. After including to
mstSet, update key values of adjacent vertices. Adjacent vertices of 0 are 1 and 7. The key
values of 1 and 7 are updated as 4 and 8. Following subgraph shows vertices and their key
values, only the vertices with finite key values are shown. The vertices included in MST are
shown in green color.
Pick the vertex with minimum key value and not already included in MST (not in mstSET).
The vertex 1 is picked and added to mstSet. So mstSet now becomes {0, 1}. Update the
key values of adjacent vertices of 1. The key value of vertex 2 becomes 8.
Pick the vertex with minimum key value and not already included in MST (not in mstSET).
We can either pick vertex 7 or vertex 2, let vertex 7 is picked. So mstSet now becomes {0,
1, 7}. Update the key values of adjacent vertices of 7. The key value of vertex 6 and 8
becomes finite (7 and 1 respectively).
143
Chapter 17. Prim’s Minimum Spanning Tree (MST))
Pick the vertex with minimum key value and not already included in MST (not in mstSET).
Vertex 6 is picked. So mstSet now becomes {0, 1, 7, 6}. Update the key values of adjacent
vertices of 6. The key value of vertex 5 and 8 are updated.
We repeat the above steps until mstSet includes all vertices of given graph. Finally, we get
the following graph.
144
Chapter 17. Prim’s Minimum Spanning Tree (MST))
145
Chapter 17. Prim’s Minimum Spanning Tree (MST))
Java
146
Chapter 17. Prim’s Minimum Spanning Tree (MST))
147
Chapter 17. Prim’s Minimum Spanning Tree (MST))
// To represent set of vertices not yet included in MST
Boolean mstSet[] = new Boolean[V];
// Initialize all keys as INFINITE
for (int i = 0; i < V; i++)
{
key[i] = Integer.MAX_VALUE;
mstSet[i] = false;
}
// Always include first 1st vertex in MST.
key[0] = 0; // Make key 0 so that this vertex is
// picked as first vertex
parent[0] = -1; // First node is always root of MST
// The MST will have V vertices
for (int count = 0; count < V-1; count++)
{
// Pick thd minimum key vertex from the set of vertices
// not yet included in MST
int u = minKey(key, mstSet);
// Add the picked vertex to the MST Set
mstSet[u] = true;
// Update key value and parent index of the adjacent
// vertices of the picked vertex. Consider only those
// vertices which are not yet included in MST
for (int v = 0; v < V; v++)
// graph[u][v] is non zero only for adjacent vertices of m
// mstSet[v] is false for vertices not yet included in MST
// Update the key only if graph[u][v] is smaller than key[v]
if (graph[u][v]!=0 && mstSet[v] == false &&
graph[u][v] < key[v])
{
parent[v] = u;
key[v] = graph[u][v];
}
}
// print the constructed MST
printMST(parent, V, graph);
}
public static void main (String[] args)
{
148
Chapter 17. Prim’s Minimum Spanning Tree (MST))
Python
149
Chapter 17. Prim’s Minimum Spanning Tree (MST))
for v in range(self.V):
if key[v] < min and mstSet[v] == False:
min = key[v]
min_index = v
return min_index
# Function to construct and print MST for a graph
# represented using adjacency matrix representation
def primMST(self):
#Key values used to pick minimum weight edge in cut
key = [sys.maxint] * self.V
parent = [None] * self.V # Array to store constructed MST
# Make key 0 so that this vertex is picked as first vertex
key[0] = 0
mstSet = [False] * self.V
parent[0] = -1 # First node is always the root of
for cout in range(self.V):
# Pick the minimum distance vertex from
# the set of vertices not yet processed.
# u is always equal to src in first iteration
u = self.minKey(key, mstSet)
# Put the minimum distance vertex in
# the shortest path tree
mstSet[u] = True
# Update dist value of the adjacent vertices
# of the picked vertex only if the current
# distance is greater than new distance and
# the vertex in not in the shotest path tree
for v in range(self.V):
# graph[u][v] is non zero only for adjacent vertices of m
# mstSet[v] is false for vertices not yet included in MST
# Update the key only if graph[u][v] is smaller than key[v]
if self.graph[u][v] > 0 and mstSet[v] == False and key[v] > self.graph[u][v]:
key[v] = self.graph[u][v]
parent[v] = u
self.printMST(parent)
g = Graph(5)
g.graph = [ [0, 2, 0, 6, 0],
150
Chapter 17. Prim’s Minimum Spanning Tree (MST))
[2, 0, 3, 8, 5],
[0, 3, 0, 0, 7],
[6, 8, 0, 0, 9],
[0, 5, 7, 9, 0]]
g.primMST();
# Contributed by Divyanshu Mehta
C#
151
Chapter 17. Prim’s Minimum Spanning Tree (MST))
152
Chapter 17. Prim’s Minimum Spanning Tree (MST))
// Update key value and parent
// index of the adjacent vertices
// of the picked vertex. Consider
// only those vertices which are
// not yet included in MST
for (int v = 0; v < V; v++)
// graph[u][v] is non zero only
// for adjacent vertices of m
// mstSet[v] is false for vertices
// not yet included in MST Update
// the key only if graph[u][v] is
// smaller than key[v]
if (graph[u,v] != 0 && mstSet[v] == false &&
graph[u,v] < key[v])
{
parent[v] = u;
key[v] = graph[u,v];
}
}
// print the constructed MST
printMST(parent, V, graph);
}
// Driver Code
public static void Main ()
{
/* Let us create the following graph
2 3
(0)--(1)--(2)
| / \ |
6| 8/ \5 |7
| / \ |
(3)-------(4)
9 */
int [,]graph = new int[,] {{0, 2, 0, 6, 0},
{2, 0, 3, 8, 5},
{0, 3, 0, 0, 7},
{6, 8, 0, 0, 9},
{0, 5, 7, 9, 0}};
// Print the solution
primMST(graph);
}
153
Chapter 17. Prim’s Minimum Spanning Tree (MST))
}
// This code is contributed by anuj_67.
Output:
Edge Weight
0 - 1 2
1 - 2 3
0 - 3 6
1 - 4 5
Time Complexity of the above program is O(V^2). If the input graph is represented using
adjacency list, then the time complexity of Prim’s algorithm can be reduced to O(E log V)
with the help of binary heap. Please see Prim’s MST for Adjacency List Representation for
more details.
Improved By : vt_m, AnkurKarmakar
Source
https://www.geeksforgeeks.org/prims-minimum-spanning-tree-mst-greedy-algo-5/
154
Chapter 18
Applications of Minimum
Spanning Tree Problem
155
Chapter 18. Applications of Minimum Spanning Tree Problem
Indirect applications.
– max bottleneck paths
– LDPC codes for error correction
– image registration with Renyi entropy
– learning salient features for real-time face verification
– reducing data storage in sequencing amino acids in a protein
– model locality of particle interactions in turbulent fluid flows
– autoconfig protocol for Ethernet bridging to avoid cycles in a network
Cluster analysis
k clustering problem can be viewed as finding an MST and deleting the k-1 most
expensive edges.
Sources:
http://www.cs.princeton.edu/courses/archive/spr07/cos226/lectures/mst.pdf
http://www.ics.uci.edu/~eppstein/161/960206.html
Source
https://www.geeksforgeeks.org/applications-of-minimum-spanning-tree/
156
Chapter 19
157
Chapter 19. Prim’s MST for Adjacency List Representation
Initially, key value of first vertex is 0 and INF (infinite) for all other vertices. So vertex 0
is extracted from Min Heap and key values of vertices adjacent to 0 (1 and 7) are updated.
Min Heap contains all vertices except vertex 0.
The vertices in green color are the vertices included in MST.
Since key value of vertex 1 is minimum among all nodes in Min Heap, it is extracted from
Min Heap and key values of vertices adjacent to 1 are updated (Key is updated if the a
vertex is not in Min Heap and previous key value is greater than the weight of edge from 1
to the adjacent). Min Heap contains all vertices except vertex 0 and 1.
Since key value of vertex 7 is minimum among all nodes in Min Heap, it is extracted from
Min Heap and key values of vertices adjacent to 7 are updated (Key is updated if the a
vertex is not in Min Heap and previous key value is greater than the weight of edge from 7
to the adjacent). Min Heap contains all vertices except vertex 0, 1 and 7.
Since key value of vertex 6 is minimum among all nodes in Min Heap, it is extracted from
Min Heap and key values of vertices adjacent to 6 are updated (Key is updated if the a
158
Chapter 19. Prim’s MST for Adjacency List Representation
vertex is not in Min Heap and previous key value is greater than the weight of edge from 6
to the adjacent). Min Heap contains all vertices except vertex 0, 1, 7 and 6.
The above steps are repeated for rest of the nodes in Min Heap till Min Heap becomes empty
C++
// C / C++ program for Prim's MST for adjacency list representation of graph
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
// A structure to represent a node in adjacency list
struct AdjListNode {
int dest;
int weight;
struct AdjListNode* next;
};
// A structure to represent an adjacency list
struct AdjList {
struct AdjListNode* head; // pointer to head node of list
};
// A structure to represent a graph. A graph is an array of adjacency lists.
// Size of array will be V (number of vertices in graph)
struct Graph {
int V;
struct AdjList* array;
};
// A utility function to create a new adjacency list node
struct AdjListNode* newAdjListNode(int dest, int weight)
159
Chapter 19. Prim’s MST for Adjacency List Representation
{
struct AdjListNode* newNode = (struct AdjListNode*)malloc(sizeof(struct AdjListNode));
newNode->dest = dest;
newNode->weight = weight;
newNode->next = NULL;
return newNode;
}
// A utility function that creates a graph of V vertices
struct Graph* createGraph(int V)
{
struct Graph* graph = (struct Graph*)malloc(sizeof(struct Graph));
graph->V = V;
// Create an array of adjacency lists. Size of array will be V
graph->array = (struct AdjList*)malloc(V * sizeof(struct AdjList));
// Initialize each adjacency list as empty by making head as NULL
for (int i = 0; i < V; ++i)
graph->array[i].head = NULL;
return graph;
}
// Adds an edge to an undirected graph
void addEdge(struct Graph* graph, int src, int dest, int weight)
{
// Add an edge from src to dest. A new node is added to the adjacency
// list of src. The node is added at the begining
struct AdjListNode* newNode = newAdjListNode(dest, weight);
newNode->next = graph->array[src].head;
graph->array[src].head = newNode;
// Since graph is undirected, add an edge from dest to src also
newNode = newAdjListNode(src, weight);
newNode->next = graph->array[dest].head;
graph->array[dest].head = newNode;
}
// Structure to represent a min heap node
struct MinHeapNode {
int v;
int key;
};
// Structure to represent a min heap
struct MinHeap {
int size; // Number of heap nodes present currently
160
Chapter 19. Prim’s MST for Adjacency List Representation
161
Chapter 19. Prim’s MST for Adjacency List Representation
if (smallest != idx) {
// The nodes to be swapped in min heap
MinHeapNode* smallestNode = minHeap->array[smallest];
MinHeapNode* idxNode = minHeap->array[idx];
// Swap positions
minHeap->pos[smallestNode->v] = idx;
minHeap->pos[idxNode->v] = smallest;
// Swap nodes
swapMinHeapNode(&minHeap->array[smallest], &minHeap->array[idx]);
minHeapify(minHeap, smallest);
}
}
// A utility function to check if the given minHeap is ampty or not
int isEmpty(struct MinHeap* minHeap)
{
return minHeap->size == 0;
}
// Standard function to extract minimum node from heap
struct MinHeapNode* extractMin(struct MinHeap* minHeap)
{
if (isEmpty(minHeap))
return NULL;
// Store the root node
struct MinHeapNode* root = minHeap->array[0];
// Replace root node with last node
struct MinHeapNode* lastNode = minHeap->array[minHeap->size - 1];
minHeap->array[0] = lastNode;
// Update position of last node
minHeap->pos[root->v] = minHeap->size - 1;
minHeap->pos[lastNode->v] = 0;
// Reduce heap size and heapify root
--minHeap->size;
minHeapify(minHeap, 0);
return root;
}
// Function to decreasy key value of a given vertex v. This function
162
Chapter 19. Prim’s MST for Adjacency List Representation
// uses pos[] of min heap to get the current index of node in min heap
void decreaseKey(struct MinHeap* minHeap, int v, int key)
{
// Get the index of v in heap array
int i = minHeap->pos[v];
// Get the node and update its key value
minHeap->array[i]->key = key;
// Travel up while the complete tree is not hepified.
// This is a O(Logn) loop
while (i && minHeap->array[i]->key < minHeap->array[(i - 1) / 2]->key) {
// Swap this node with its parent
minHeap->pos[minHeap->array[i]->v] = (i - 1) / 2;
minHeap->pos[minHeap->array[(i - 1) / 2]->v] = i;
swapMinHeapNode(&minHeap->array[i], &minHeap->array[(i - 1) / 2]);
// move to parent index
i = (i - 1) / 2;
}
}
// A utility function to check if a given vertex
// 'v' is in min heap or not
bool isInMinHeap(struct MinHeap* minHeap, int v)
{
if (minHeap->pos[v] < minHeap->size)
return true;
return false;
}
// A utility function used to print the constructed MST
void printArr(int arr[], int n)
{
for (int i = 1; i < n; ++i)
printf("%d - %d\n", arr[i], i);
}
// The main function that constructs Minimum Spanning Tree (MST)
// using Prim's algorithm
void PrimMST(struct Graph* graph)
{
int V = graph->V; // Get the number of vertices in graph
int parent[V]; // Array to store constructed MST
int key[V]; // Key values used to pick minimum weight edge in cut
// minHeap represents set E
struct MinHeap* minHeap = createMinHeap(V);
163
Chapter 19. Prim’s MST for Adjacency List Representation
// Initialize min heap with all vertices. Key value of
// all vertices (except 0th vertex) is initially infinite
for (int v = 1; v < V; ++v) {
parent[v] = -1;
key[v] = INT_MAX;
minHeap->array[v] = newMinHeapNode(v, key[v]);
minHeap->pos[v] = v;
}
// Make key value of 0th vertex as 0 so that it
// is extracted first
key[0] = 0;
minHeap->array[0] = newMinHeapNode(0, key[0]);
minHeap->pos[0] = 0;
// Initially size of min heap is equal to V
minHeap->size = V;
// In the followin loop, min heap contains all nodes
// not yet added to MST.
while (!isEmpty(minHeap)) {
// Extract the vertex with minimum key value
struct MinHeapNode* minHeapNode = extractMin(minHeap);
int u = minHeapNode->v; // Store the extracted vertex number
// Traverse through all adjacent vertices of u (the extracted
// vertex) and update their key values
struct AdjListNode* pCrawl = graph->array[u].head;
while (pCrawl != NULL) {
int v = pCrawl->dest;
// If v is not yet included in MST and weight of u-v is
// less than key value of v, then update key value and
// parent of v
if (isInMinHeap(minHeap, v) && pCrawl->weight < key[v]) {
key[v] = pCrawl->weight;
parent[v] = u;
decreaseKey(minHeap, v, key[v]);
}
pCrawl = pCrawl->next;
}
}
// print edges of MST
printArr(parent, V);
}
164
Chapter 19. Prim’s MST for Adjacency List Representation
Java
165
Chapter 19. Prim’s MST for Adjacency List Representation
}
}
static class Graph {
// Number of vertices in the graph
int V;
// List of adjacent nodes of a given vertex
LinkedList<node1>[] adj;
// Constructor
Graph(int e)
{
V = e;
adj = new LinkedList[V];
for (int o = 0; o < V; o++)
adj[o] = new LinkedList<>();
}
}
// class to represent a node in PriorityQueue
// Stores a vertex and its corresponding
// key value
class node {
int vertex;
int key;
}
// Comparator class created for PriorityQueue
// returns 1 if node0.key > node1.key
// returns 0 if node0.key < node1.key and
// returns -1 otherwise
class comparator implements Comparator<node> {
@Override
public int compare(node node0, node node1)
{
return node0.key - node1.key;
}
}
// method to add an edge
// between two vertices
void addEdge(Graph graph, int src, int dest, int weight)
{
node1 node0 = new node1(dest, weight);
node1 node = new node1(src, weight);
166
Chapter 19. Prim’s MST for Adjacency List Representation
graph.adj[src].addLast(node0);
graph.adj[dest].addLast(node);
}
// method used to find the mst
void prims_mst(Graph graph)
{
// Whether a vertex is in PriorityQueue or not
Boolean[] mstset = new Boolean[graph.V];
node[] e = new node[graph.V];
// Stores the parents of a vertex
int[] parent = new int[graph.V];
for (int o = 0; o < graph.V; o++)
e[o] = new node();
for (int o = 0; o < graph.V; o++) {
// Initialize to false
mstset[o] = false;
// Initialize key values to infinity
e[o].key = Integer.MAX_VALUE;
e[o].vertex = o;
parent[o] = -1;
}
// Include the source vertex in mstset
mstset[0] = true;
// Set key value to 0
// so that it is extracted first
// out of PriorityQueue
e[0].key = 0;
// PriorityQueue
PriorityQueue<node> queue = new PriorityQueue<>(graph.V, new comparator());
for (int o = 0; o < graph.V; o++)
queue.add(e[o]);
// Loops until the PriorityQueue is not empty
while (!queue.isEmpty()) {
// Extracts a node with min key value
node node0 = queue.poll();
167
Chapter 19. Prim’s MST for Adjacency List Representation
// Include that node into mstset
mstset[node0.vertex] = true;
// For all adjacent vertex of the extracted vertex V
for (node1 iterator : graph.adj[node0.vertex]) {
// If V is in PriorityQueue
if (mstset[iterator.dest] == false) {
// If the key value of the adjacent vertex is
// more than the extracted key
// update the key value of adjacent vertex
// to update first remove and add the updated vertex
if (e[iterator.dest].key > iterator.weight) {
queue.remove(e[iterator.dest]);
e[iterator.dest].key = iterator.weight;
queue.add(e[iterator.dest]);
parent[iterator.dest] = node0.vertex;
}
}
}
}
// Prints the vertex pair of mst
for (int o = 1; o < graph.V; o++)
System.out.println(parent[o] + " "
+ "-"
+ " " + o);
}
public static void main(String[] args)
{
int V = 9;
Graph graph = new Graph(V);
prims e = new prims();
e.addEdge(graph, 0, 1, 4);
e.addEdge(graph, 0, 7, 8);
e.addEdge(graph, 1, 2, 8);
e.addEdge(graph, 1, 7, 11);
e.addEdge(graph, 2, 3, 7);
e.addEdge(graph, 2, 8, 2);
e.addEdge(graph, 2, 5, 4);
e.addEdge(graph, 3, 4, 9);
e.addEdge(graph, 3, 5, 14);
e.addEdge(graph, 4, 5, 10);
168
Chapter 19. Prim’s MST for Adjacency List Representation
e.addEdge(graph, 5, 6, 2);
e.addEdge(graph, 6, 7, 1);
e.addEdge(graph, 6, 8, 6);
e.addEdge(graph, 7, 8, 7);
// Method invoked
e.prims_mst(graph);
}
}
// This code is contributed by Vikash Kumar Dubey
Python
169
Chapter 19. Prim’s MST for Adjacency List Representation
smallest = left
if right < self.size and self.array[right][1] < \
self.array[smallest][1]:
smallest = right
# The nodes to be swapped in min heap
# if idx is not smallest
if smallest != idx:
# Swap positions
self.pos[ self.array[smallest][0] ] = idx
self.pos[ self.array[idx][0] ] = smallest
# Swap nodes
self.swapMinHeapNode(smallest, idx)
self.minHeapify(smallest)
# Standard function to extract minimum node from heap
def extractMin(self):
# Return NULL wif heap is empty
if self.isEmpty() == True:
return
# Store the root node
root = self.array[0]
# Replace root node with last node
lastNode = self.array[self.size - 1]
self.array[0] = lastNode
# Update position of last node
self.pos[lastNode[0]] = 0
self.pos[root[0]] = self.size - 1
# Reduce heap size and heapify root
self.size -= 1
self.minHeapify(0)
return root
def isEmpty(self):
return True if self.size == 0 else False
def decreaseKey(self, v, dist):
170
Chapter 19. Prim’s MST for Adjacency List Representation
171
Chapter 19. Prim’s MST for Adjacency List Representation
172
Chapter 19. Prim’s MST for Adjacency List Representation
# Traverse through all adjacent vertices of u
# (the extracted vertex) and update their
# distance values
for pCrawl in self.graph[u]:
v = pCrawl[0]
# If shortest distance to v is not finalized
# yet, and distance to v through u is less than
# its previously calculated distance
if minHeap.isInMinHeap(v) and pCrawl[1] < key[v]:
key[v] = pCrawl[1]
parent[v] = u
# update distance value in min heap also
minHeap.decreaseKey(v, key[v])
printArr(parent, V)
# Driver program to test the above functions
graph = Graph(9)
graph.addEdge(0, 1, 4)
graph.addEdge(0, 7, 8)
graph.addEdge(1, 2, 8)
graph.addEdge(1, 7, 11)
graph.addEdge(2, 3, 7)
graph.addEdge(2, 8, 2)
graph.addEdge(2, 5, 4)
graph.addEdge(3, 4, 9)
graph.addEdge(3, 5, 14)
graph.addEdge(4, 5, 10)
graph.addEdge(5, 6, 2)
graph.addEdge(6, 7, 1)
graph.addEdge(6, 8, 6)
graph.addEdge(7, 8, 7)
graph.PrimMST()
# This code is contributed by Divyanshu Mehta
Output:
0 - 1
5 - 2
2 - 3
3 - 4
6 - 5
173
Chapter 19. Prim’s MST for Adjacency List Representation
7 - 6
0 - 7
2 - 8
Time Complexity: The time complexity of the above code/algorithm looks O(V^2) as
there are two nested while loops. If we take a closer look, we can observe that the statements
in inner loop are executed O(V+E) times (similar to BFS). The inner loop has decreaseKey()
operation which takes O(LogV) time. So overall time complexity is O(E+V)*O(LogV) which
is O((E+V)*LogV) = O(ELogV) (For a connected graph, V = O(E))
References:
Introduction to Algorithms by Clifford Stein, Thomas H. Cormen, Charles E. Leiserson,
Ronald L.
http://en.wikipedia.org/wiki/Prim’s_algorithm
This article is compiled by Aashish Barnwal and reviewed by GeeksforGeeks team. Please
write comments if you find anything incorrect, or you want to share more information about
the topic discussed above.
Improved By : VikashDubey, Sumon Nath
Source
https://www.geeksforgeeks.org/prims-mst-for-adjacency-list-representation-greedy-algo-6/
174
Chapter 20
The step#2 uses Union-Find algorithm to detect cycle. So we recommend to read following
post as a prerequisite.
Union-Find Algorithm Set 1 (Detect Cycle in a Graph)
Union-Find Algorithm Set 2 (Union By Rank and Path Compression)
The algorithm is a Greedy Algorithm. The Greedy Choice is to pick the smallest weight
edge that does not cause a cycle in the MST constructed so far. Let us understand it with
an example: Consider the below input graph.
175
Chapter 20. Kruskal’s Minimum Spanning Tree Algorithm
The graph contains 9 vertices and 14 edges. So, the minimum spanning tree formed will be
having (9 – 1) = 8 edges.
After sorting:
Weight Src Dest
1 7 6
2 8 2
2 6 5
4 0 1
4 2 5
6 8 6
7 2 3
7 7 8
8 0 7
8 1 2
9 3 4
10 5 4
11 1 7
14 3 5
Now pick all edges one by one from sorted list of edges
1. Pick edge 7-6: No cycle is formed, include it.
176
Chapter 20. Kruskal’s Minimum Spanning Tree Algorithm
6. Pick edge 8-6: Since including this edge results in cycle, discard it.
7. Pick edge 2-3: No cycle is formed, include it.
8. Pick edge 7-8: Since including this edge results in cycle, discard it.
9. Pick edge 0-7: No cycle is formed, include it.
177
Chapter 20. Kruskal’s Minimum Spanning Tree Algorithm
10. Pick edge 1-2: Since including this edge results in cycle, discard it.
11. Pick edge 3-4: No cycle is formed, include it.
Since the number of edges included equals (V – 1), the algorithm stops here.
C/C++
178
Chapter 20. Kruskal’s Minimum Spanning Tree Algorithm
179
Chapter 20. Kruskal’s Minimum Spanning Tree Algorithm
180
Chapter 20. Kruskal’s Minimum Spanning Tree Algorithm
result[e++] = next_edge;
Union(subsets, x, y);
}
// Else discard the next_edge
}
// print the contents of result[] to display the
// built MST
printf("Following are the edges in the constructed MST\n");
for (i = 0; i < e; ++i)
printf("%d -- %d == %d\n", result[i].src, result[i].dest,
result[i].weight);
return;
}
// Driver program to test above functions
int main()
{
/* Let us create following weighted graph
10
0--------1
| \ |
6| 5\ |15
| \ |
2--------3
4 */
int V = 4; // Number of vertices in graph
int E = 5; // Number of edges in graph
struct Graph* graph = createGraph(V, E);
// add edge 0-1
graph->edge[0].src = 0;
graph->edge[0].dest = 1;
graph->edge[0].weight = 10;
// add edge 0-2
graph->edge[1].src = 0;
graph->edge[1].dest = 2;
graph->edge[1].weight = 6;
// add edge 0-3
graph->edge[2].src = 0;
graph->edge[2].dest = 3;
graph->edge[2].weight = 5;
// add edge 1-3
graph->edge[3].src = 1;
181
Chapter 20. Kruskal’s Minimum Spanning Tree Algorithm
graph->edge[3].dest = 3;
graph->edge[3].weight = 15;
// add edge 2-3
graph->edge[4].src = 2;
graph->edge[4].dest = 3;
graph->edge[4].weight = 4;
KruskalMST(graph);
return 0;
}
Java
182
Chapter 20. Kruskal’s Minimum Spanning Tree Algorithm
{
V = v;
E = e;
edge = new Edge[E];
for (int i=0; i<e; ++i)
edge[i] = new Edge();
}
// A utility function to find set of an element i
// (uses path compression technique)
int find(subset subsets[], int i)
{
// find root and make root as parent of i (path compression)
if (subsets[i].parent != i)
subsets[i].parent = find(subsets, subsets[i].parent);
return subsets[i].parent;
}
// A function that does union of two sets of x and y
// (uses union by rank)
void Union(subset subsets[], int x, int y)
{
int xroot = find(subsets, x);
int yroot = find(subsets, y);
// Attach smaller rank tree under root of high rank tree
// (Union by Rank)
if (subsets[xroot].rank < subsets[yroot].rank)
subsets[xroot].parent = yroot;
else if (subsets[xroot].rank > subsets[yroot].rank)
subsets[yroot].parent = xroot;
// If ranks are same, then make one as root and increment
// its rank by one
else
{
subsets[yroot].parent = xroot;
subsets[xroot].rank++;
}
}
// The main function to construct MST using Kruskal's algorithm
void KruskalMST()
{
Edge result[] = new Edge[V]; // Tnis will store the resultant MST
int e = 0; // An index variable, used for result[]
int i = 0; // An index variable, used for sorted edges
183
Chapter 20. Kruskal’s Minimum Spanning Tree Algorithm
184
Chapter 20. Kruskal’s Minimum Spanning Tree Algorithm
185
Chapter 20. Kruskal’s Minimum Spanning Tree Algorithm
}
//This code is contributed by Aakash Hasija
Python
186
Chapter 20. Kruskal’s Minimum Spanning Tree Algorithm
rank[xroot] += 1
# The main function to construct MST using Kruskal's
# algorithm
def KruskalMST(self):
result =[] #This will store the resultant MST
i = 0 # An index variable, used for sorted edges
e = 0 # An index variable, used for result[]
# Step 1: Sort all the edges in non-decreasing
# order of their
# weight. If we are not allowed to change the
# given graph, we can create a copy of graph
self.graph = sorted(self.graph,key=lambda item: item[2])
parent = [] ; rank = []
# Create V subsets with single elements
for node in range(self.V):
parent.append(node)
rank.append(0)
# Number of edges to be taken is equal to V-1
while e < self.V -1 :
# Step 2: Pick the smallest edge and increment
# the index for next iteration
u,v,w = self.graph[i]
i = i + 1
x = self.find(parent, u)
y = self.find(parent ,v)
# If including this edge does't cause cycle,
# include it in result and increment the index
# of result for next edge
if x != y:
e = e + 1
result.append([u,v,w])
self.union(parent, rank, x, y)
# Else discard the edge
# print the contents of result[] to display the built MST
print "Following are the edges in the constructed MST"
for u,v,weight in result:
#print str(u) + " -- " + str(v) + " == " + str(weight)
print ("%d -- %d == %d" % (u,v,weight))
187
Chapter 20. Kruskal’s Minimum Spanning Tree Algorithm
# Driver code
g = Graph(4)
g.addEdge(0, 1, 10)
g.addEdge(0, 2, 6)
g.addEdge(0, 3, 5)
g.addEdge(1, 3, 15)
g.addEdge(2, 3, 4)
g.KruskalMST()
#This code is contributed by Neelam Yadav
Time Complexity: O(ElogE) or O(ElogV). Sorting of edges takes O(ELogE) time. After
sorting, we iterate through all edges and apply find-union algorithm. The find and union
operations can take atmost O(LogV) time. So overall complexity is O(ELogE + ELogV)
time. The value of E can be atmost O(V2 ), so O(LogV) are O(LogE) same. Therefore,
overall time complexity is O(ElogE) or O(ElogV)
References:
http://www.ics.uci.edu/~eppstein/161/960206.html
http://en.wikipedia.org/wiki/Minimum_spanning_tree
This article is compiled by Aashish Barnwal and reviewed by GeeksforGeeks team. Please
write comments if you find anything incorrect, or you want to share more information about
the topic discussed above.
Source
https://www.geeksforgeeks.org/kruskals-minimum-spanning-tree-algorithm-greedy-algo-2/
188
Chapter 21
Dijsktra’s algorithm
Given a graph and a source vertex in the graph, find shortest paths from source to all
vertices in the given graph.
Dijkstra’s algorithm is very similar to Prim’s algorithm for minimum spanning tree. Like
Prim’s MST, we generate a SPT (shortest path tree) with given source as root. We maintain
two sets, one set contains vertices included in shortest path tree, other set includes vertices
not yet included in shortest path tree. At every step of the algorithm, we find a vertex
which is in the other set (set of not yet included) and has a minimum distance from the
source.
Below are the detailed steps used in Dijkstra’s algorithm to find the shortest path from a
single source vertex to all other vertices in the given graph.
Algorithm
1) Create a set sptSet (shortest path tree set) that keeps track of vertices included in shortest
path tree, i.e., whose minimum distance from source is calculated and finalized. Initially,
this set is empty.
2) Assign a distance value to all vertices in the input graph. Initialize all distance values as
INFINITE. Assign distance value as 0 for the source vertex so that it is picked first.
3) While sptSet doesn’t include all vertices
….a) Pick a vertex u which is not there in sptSet and has minimum distance value.
….b) Include u to sptSet.
….c) Update distance value of all adjacent vertices of u. To update the distance values,
iterate through all adjacent vertices. For every adjacent vertex v, if sum of distance value
of u (from source) and weight of edge u-v, is less than the distance value of v, then update
the distance value of v.
Let us understand with the following example:
189
Chapter 21. Dijkstra’s shortest path algorithm
The set sptSet is initially empty and distances assigned to vertices are {0, INF, INF, INF,
INF, INF, INF, INF} where INF indicates infinite. Now pick the vertex with minimum
distance value. The vertex 0 is picked, include it in sptSet. So sptSet becomes {0}. After
including 0 to sptSet, update distance values of its adjacent vertices. Adjacent vertices of
0 are 1 and 7. The distance values of 1 and 7 are updated as 4 and 8. Following subgraph
shows vertices and their distance values, only the vertices with finite distance values are
shown. The vertices included in SPT are shown in green colour.
Pick the vertex with minimum distance value and not already included in SPT (not in
sptSET). The vertex 1 is picked and added to sptSet. So sptSet now becomes {0, 1}.
Update the distance values of adjacent vertices of 1. The distance value of vertex 2 becomes
12.
Pick the vertex with minimum distance value and not already included in SPT (not in
sptSET). Vertex 7 is picked. So sptSet now becomes {0, 1, 7}. Update the distance values
of adjacent vertices of 7. The distance value of vertex 6 and 8 becomes finite (15 and 9
respectively).
190
Chapter 21. Dijkstra’s shortest path algorithm
Pick the vertex with minimum distance value and not already included in SPT (not in
sptSET). Vertex 6 is picked. So sptSet now becomes {0, 1, 7, 6}. Update the distance
values of adjacent vertices of 6. The distance value of vertex 5 and 8 are updated.
We repeat the above steps until sptSet doesn’t include all vertices of given graph. Finally,
we get the following Shortest Path Tree (SPT).
191
Chapter 21. Dijkstra’s shortest path algorithm
#define V 9
// A utility function to find the vertex with minimum distance value, from
// the set of vertices not yet included in shortest path tree
int minDistance(int dist[], bool sptSet[])
{
// Initialize min value
int min = INT_MAX, min_index;
for (int v = 0; v < V; v++)
if (sptSet[v] == false && dist[v] <= min)
min = dist[v], min_index = v;
return min_index;
}
// A utility function to print the constructed distance array
int printSolution(int dist[], int n)
{
printf("Vertex Distance from Source\n");
for (int i = 0; i < V; i++)
printf("%d tt %d\n", i, dist[i]);
}
// Function that implements Dijkstra's single source shortest path algorithm
// for a graph represented using adjacency matrix representation
void dijkstra(int graph[V][V], int src)
{
int dist[V]; // The output array. dist[i] will hold the shortest
// distance from src to i
bool sptSet[V]; // sptSet[i] will true if vertex i is included in shortest
// path tree or shortest distance from src to i is finalized
// Initialize all distances as INFINITE and stpSet[] as false
for (int i = 0; i < V; i++)
dist[i] = INT_MAX, sptSet[i] = false;
// Distance of source vertex from itself is always 0
dist[src] = 0;
// Find shortest path for all vertices
for (int count = 0; count < V-1; count++)
{
// Pick the minimum distance vertex from the set of vertices not
// yet processed. u is always equal to src in the first iteration.
int u = minDistance(dist, sptSet);
192
Chapter 21. Dijkstra’s shortest path algorithm
Java
193
Chapter 21. Dijkstra’s shortest path algorithm
// A utility function to find the vertex with minimum distance value,
// from the set of vertices not yet included in shortest path tree
static final int V=9;
int minDistance(int dist[], Boolean sptSet[])
{
// Initialize min value
int min = Integer.MAX_VALUE, min_index=-1;
for (int v = 0; v < V; v++)
if (sptSet[v] == false && dist[v] <= min)
{
min = dist[v];
min_index = v;
}
return min_index;
}
// A utility function to print the constructed distance array
void printSolution(int dist[], int n)
{
System.out.println("Vertex Distance from Source");
for (int i = 0; i < V; i++)
System.out.println(i+" tt "+dist[i]);
}
// Funtion that implements Dijkstra's single source shortest path
// algorithm for a graph represented using adjacency matrix
// representation
void dijkstra(int graph[][], int src)
{
int dist[] = new int[V]; // The output array. dist[i] will hold
// the shortest distance from src to i
// sptSet[i] will true if vertex i is included in shortest
// path tree or shortest distance from src to i is finalized
Boolean sptSet[] = new Boolean[V];
// Initialize all distances as INFINITE and stpSet[] as false
for (int i = 0; i < V; i++)
{
dist[i] = Integer.MAX_VALUE;
sptSet[i] = false;
}
// Distance of source vertex from itself is always 0
dist[src] = 0;
194
Chapter 21. Dijkstra’s shortest path algorithm
195
Chapter 21. Dijkstra’s shortest path algorithm
Python
196
Chapter 21. Dijkstra’s shortest path algorithm
# Pick the minimum distance vertex from
# the set of vertices not yet processed.
# u is always equal to src in first iteration
u = self.minDistance(dist, sptSet)
# Put the minimum distance vertex in the
# shotest path tree
sptSet[u] = True
# Update dist value of the adjacent vertices
# of the picked vertex only if the current
# distance is greater than new distance and
# the vertex in not in the shotest path tree
for v in range(self.V):
if self.graph[u][v] > 0 and sptSet[v] == False and
dist[v] > dist[u] + self.graph[u][v]:
dist[v] = dist[u] + self.graph[u][v]
self.printSolution(dist)
# Driver program
g = Graph(9)
g.graph = [[0, 4, 0, 0, 0, 0, 0, 8, 0],
[4, 0, 8, 0, 0, 0, 0, 11, 0],
[0, 8, 0, 7, 0, 4, 0, 0, 2],
[0, 0, 7, 0, 9, 14, 0, 0, 0],
[0, 0, 0, 9, 0, 10, 0, 0, 0],
[0, 0, 4, 14, 10, 0, 2, 0, 0],
[0, 0, 0, 0, 0, 2, 0, 1, 6],
[8, 11, 0, 0, 0, 0, 1, 0, 7],
[0, 0, 2, 0, 0, 0, 6, 7, 0]
];
g.dijkstra(0);
# This code is contributed by Divyanshu Mehta
Output:
197
Chapter 21. Dijkstra’s shortest path algorithm
7 8
8 14
Notes:
1) The code calculates shortest distance, but doesn’t calculate the path information. We
can create a parent array, update the parent array when distance is updated (like prim’s
implementation) and use it show the shortest path from source to different vertices.
2) The code is for undirected graph, same dijkstra function can be used for directed graphs
also.
3) The code finds shortest distances from source to all vertices. If we are interested only in
shortest distance from the source to a single target, we can break the for the loop when the
picked minimum distance vertex is equal to target (Step 3.a of the algorithm).
4) Time Complexity of the implementation is O(V^2). If the input graph is represented
using adjacency list, it can be reduced to O(E log V) with the help of binary heap. Please
see
Dijkstra’s Algorithm for Adjacency List Representation for more details.
5) Dijkstra’s algorithm doesn’t work for graphs with negative weight edges. For graphs with
negative weight edges, Bellman–Ford algorithm can be used, we will soon be discussing it
as a separate post.
Dijkstra’s Algorithm for Adjacency List Representation
Printing Paths in Dijkstra’s Shortest Path Algorithm
Dijkstra’s shortest path algorithm using set in STL
Source
https://www.geeksforgeeks.org/dijkstras-shortest-path-algorithm-greedy-algo-7/
198
Chapter 22
199
Chapter 22. Dijkstra’s Algorithm for Adjacency List Representation
Let us understand with the following example. Let the given source vertex be 0
Initially, distance value of source vertex is 0 and INF (infinite) for all other vertices. So
source vertex is extracted from Min Heap and distance values of vertices adjacent to 0 (1
and 7) are updated. Min Heap contains all vertices except vertex 0.
The vertices in green color are the vertices for which minimum distances are finalized and
are not in Min Heap
Since distance value of vertex 1 is minimum among all nodes in Min Heap, it is extracted from
Min Heap and distance values of vertices adjacent to 1 are updated (distance is updated if
the a vertex is not in Min Heap and distance through 1 is shorter than the previous distance).
Min Heap contains all vertices except vertex 0 and 1.
Pick the vertex with minimum distance value from min heap. Vertex 7 is picked. So min
heap now contains all vertices except 0, 1 and 7. Update the distance values of adjacent
vertices of 7. The distance value of vertex 6 and 8 becomes finite (15 and 9 respectively).
200
Chapter 22. Dijkstra’s Algorithm for Adjacency List Representation
Pick the vertex with minimum distance from min heap. Vertex 6 is picked. So min heap now
contains all vertices except 0, 1, 7 and 6. Update the distance values of adjacent vertices of
6. The distance value of vertex 5 and 8 are updated.
Above steps are repeated till min heap doesn’t become empty. Finally, we get the following
shortest path tree.
C++
201
Chapter 22. Dijkstra’s Algorithm for Adjacency List Representation
};
// A structure to represent an adjacency liat
struct AdjList
{
struct AdjListNode *head; // pointer to head node of list
};
// A structure to represent a graph. A graph is an array of adjacency lists.
// Size of array will be V (number of vertices in graph)
struct Graph
{
int V;
struct AdjList* array;
};
// A utility function to create a new adjacency list node
struct AdjListNode* newAdjListNode(int dest, int weight)
{
struct AdjListNode* newNode =
(struct AdjListNode*) malloc(sizeof(struct AdjListNode));
newNode->dest = dest;
newNode->weight = weight;
newNode->next = NULL;
return newNode;
}
// A utility function that creates a graph of V vertices
struct Graph* createGraph(int V)
{
struct Graph* graph = (struct Graph*) malloc(sizeof(struct Graph));
graph->V = V;
// Create an array of adjacency lists. Size of array will be V
graph->array = (struct AdjList*) malloc(V * sizeof(struct AdjList));
// Initialize each adjacency list as empty by making head as NULL
for (int i = 0; i < V; ++i)
graph->array[i].head = NULL;
return graph;
}
// Adds an edge to an undirected graph
void addEdge(struct Graph* graph, int src, int dest, int weight)
{
// Add an edge from src to dest. A new node is added to the adjacency
// list of src. The node is added at the begining
202
Chapter 22. Dijkstra’s Algorithm for Adjacency List Representation
203
Chapter 22. Dijkstra’s Algorithm for Adjacency List Representation
// A utility function to swap two nodes of min heap. Needed for min heapify
void swapMinHeapNode(struct MinHeapNode** a, struct MinHeapNode** b)
{
struct MinHeapNode* t = *a;
*a = *b;
*b = t;
}
// A standard function to heapify at given idx
// This function also updates position of nodes when they are swapped.
// Position is needed for decreaseKey()
void minHeapify(struct MinHeap* minHeap, int idx)
{
int smallest, left, right;
smallest = idx;
left = 2 * idx + 1;
right = 2 * idx + 2;
if (left < minHeap->size &&
minHeap->array[left]->dist < minHeap->array[smallest]->dist )
smallest = left;
if (right < minHeap->size &&
minHeap->array[right]->dist < minHeap->array[smallest]->dist )
smallest = right;
if (smallest != idx)
{
// The nodes to be swapped in min heap
MinHeapNode *smallestNode = minHeap->array[smallest];
MinHeapNode *idxNode = minHeap->array[idx];
// Swap positions
minHeap->pos[smallestNode->v] = idx;
minHeap->pos[idxNode->v] = smallest;
// Swap nodes
swapMinHeapNode(&minHeap->array[smallest], &minHeap->array[idx]);
minHeapify(minHeap, smallest);
}
}
// A utility function to check if the given minHeap is ampty or not
int isEmpty(struct MinHeap* minHeap)
{
return minHeap->size == 0;
204
Chapter 22. Dijkstra’s Algorithm for Adjacency List Representation
}
// Standard function to extract minimum node from heap
struct MinHeapNode* extractMin(struct MinHeap* minHeap)
{
if (isEmpty(minHeap))
return NULL;
// Store the root node
struct MinHeapNode* root = minHeap->array[0];
// Replace root node with last node
struct MinHeapNode* lastNode = minHeap->array[minHeap->size - 1];
minHeap->array[0] = lastNode;
// Update position of last node
minHeap->pos[root->v] = minHeap->size-1;
minHeap->pos[lastNode->v] = 0;
// Reduce heap size and heapify root
--minHeap->size;
minHeapify(minHeap, 0);
return root;
}
// Function to decreasy dist value of a given vertex v. This function
// uses pos[] of min heap to get the current index of node in min heap
void decreaseKey(struct MinHeap* minHeap, int v, int dist)
{
// Get the index of v in heap array
int i = minHeap->pos[v];
// Get the node and update its dist value
minHeap->array[i]->dist = dist;
// Travel up while the complete tree is not hepified.
// This is a O(Logn) loop
while (i && minHeap->array[i]->dist < minHeap->array[(i - 1) / 2]->dist)
{
// Swap this node with its parent
minHeap->pos[minHeap->array[i]->v] = (i-1)/2;
minHeap->pos[minHeap->array[(i-1)/2]->v] = i;
swapMinHeapNode(&minHeap->array[i], &minHeap->array[(i - 1) / 2]);
// move to parent index
i = (i - 1) / 2;
}
205
Chapter 22. Dijkstra’s Algorithm for Adjacency List Representation
}
// A utility function to check if a given vertex
// 'v' is in min heap or not
bool isInMinHeap(struct MinHeap *minHeap, int v)
{
if (minHeap->pos[v] < minHeap->size)
return true;
return false;
}
// A utility function used to print the solution
void printArr(int dist[], int n)
{
printf("Vertex Distance from Source\n");
for (int i = 0; i < n; ++i)
printf("%d \t\t %d\n", i, dist[i]);
}
// The main function that calulates distances of shortest paths from src to all
// vertices. It is a O(ELogV) function
void dijkstra(struct Graph* graph, int src)
{
int V = graph->V;// Get the number of vertices in graph
int dist[V]; // dist values used to pick minimum weight edge in cut
// minHeap represents set E
struct MinHeap* minHeap = createMinHeap(V);
// Initialize min heap with all vertices. dist value of all vertices
for (int v = 0; v < V; ++v)
{
dist[v] = INT_MAX;
minHeap->array[v] = newMinHeapNode(v, dist[v]);
minHeap->pos[v] = v;
}
// Make dist value of src vertex as 0 so that it is extracted first
minHeap->array[src] = newMinHeapNode(src, dist[src]);
minHeap->pos[src] = src;
dist[src] = 0;
decreaseKey(minHeap, src, dist[src]);
// Initially size of min heap is equal to V
minHeap->size = V;
// In the followin loop, min heap contains all nodes
// whose shortest distance is not yet finalized.
206
Chapter 22. Dijkstra’s Algorithm for Adjacency List Representation
while (!isEmpty(minHeap))
{
// Extract the vertex with minimum distance value
struct MinHeapNode* minHeapNode = extractMin(minHeap);
int u = minHeapNode->v; // Store the extracted vertex number
// Traverse through all adjacent vertices of u (the extracted
// vertex) and update their distance values
struct AdjListNode* pCrawl = graph->array[u].head;
while (pCrawl != NULL)
{
int v = pCrawl->dest;
// If shortest distance to v is not finalized yet, and distance to v
// through u is less than its previously calculated distance
if (isInMinHeap(minHeap, v) && dist[u] != INT_MAX &&
pCrawl->weight + dist[u] < dist[v])
{
dist[v] = dist[u] + pCrawl->weight;
// update distance value in min heap also
decreaseKey(minHeap, v, dist[v]);
}
pCrawl = pCrawl->next;
}
}
// print the calculated shortest distances
printArr(dist, V);
}
// Driver program to test above functions
int main()
{
// create the graph given in above fugure
int V = 9;
struct Graph* graph = createGraph(V);
addEdge(graph, 0, 1, 4);
addEdge(graph, 0, 7, 8);
addEdge(graph, 1, 2, 8);
addEdge(graph, 1, 7, 11);
addEdge(graph, 2, 3, 7);
addEdge(graph, 2, 8, 2);
addEdge(graph, 2, 5, 4);
addEdge(graph, 3, 4, 9);
addEdge(graph, 3, 5, 14);
addEdge(graph, 4, 5, 10);
207
Chapter 22. Dijkstra’s Algorithm for Adjacency List Representation
addEdge(graph, 5, 6, 2);
addEdge(graph, 6, 7, 1);
addEdge(graph, 6, 8, 6);
addEdge(graph, 7, 8, 7);
dijkstra(graph, 0);
return 0;
}
Python
208
Chapter 22. Dijkstra’s Algorithm for Adjacency List Representation
smallest = left
if right < self.size and self.array[right][1]\
< self.array[smallest][1]:
smallest = right
# The nodes to be swapped in min
# heap if idx is not smallest
if smallest != idx:
# Swap positions
self.pos[ self.array[smallest][0] ] = idx
self.pos[ self.array[idx][0] ] = smallest
# Swap nodes
self.swapMinHeapNode(smallest, idx)
self.minHeapify(smallest)
# Standard function to extract minimum
# node from heap
def extractMin(self):
# Return NULL wif heap is empty
if self.isEmpty() == True:
return
# Store the root node
root = self.array[0]
# Replace root node with last node
lastNode = self.array[self.size - 1]
self.array[0] = lastNode
# Update position of last node
self.pos[lastNode[0]] = 0
self.pos[root[0]] = self.size - 1
# Reduce heap size and heapify root
self.size -= 1
self.minHeapify(0)
return root
def isEmpty(self):
return True if self.size == 0 else False
def decreaseKey(self, v, dist):
209
Chapter 22. Dijkstra’s Algorithm for Adjacency List Representation
# Get the index of v in heap array
i = self.pos[v]
# Get the node and update its dist value
self.array[i][1] = dist
# Travel up while the complete tree is
# not hepified. This is a O(Logn) loop
while i > 0 and self.array[i][1] < self.array[(i - 1) / 2][1]:
# Swap this node with its parent
self.pos[ self.array[i][0] ] = (i-1)/2
self.pos[ self.array[(i-1)/2][0] ] = i
self.swapMinHeapNode(i, (i - 1)/2 )
# move to parent index
i = (i - 1) / 2;
# A utility function to check if a given
# vertex 'v' is in min heap or not
def isInMinHeap(self, v):
if self.pos[v] < self.size:
return True
return False
def printArr(dist, n):
print "Vertex\tDistance from source"
for i in range(n):
print "%d\t\t%d" % (i,dist[i])
class Graph():
def __init__(self, V):
self.V = V
self.graph = defaultdict(list)
# Adds an edge to an undirected graph
def addEdge(self, src, dest, weight):
# Add an edge from src to dest. A new node
# is added to the adjacency list of src. The
# node is added at the begining. The first
# element of the node has the destination
210
Chapter 22. Dijkstra’s Algorithm for Adjacency List Representation
211
Chapter 22. Dijkstra’s Algorithm for Adjacency List Representation
Output:
212
Chapter 22. Dijkstra’s Algorithm for Adjacency List Representation
7 8
8 14
Time Complexity: The time complexity of the above code/algorithm looks O(V^2) as
there are two nested while loops. If we take a closer look, we can observe that the statements
in inner loop are executed O(V+E) times (similar to BFS). The inner loop has decreaseKey()
operation which takes O(LogV) time. So overall time complexity is O(E+V)*O(LogV) which
is O((E+V)*LogV) = O(ELogV)
Note that the above code uses Binary Heap for Priority Queue implementation. Time com-
plexity can be reduced to O(E + VLogV) using Fibonacci Heap. The reason is, Fibonacci
Heap takes O(1) time for decrease-key operation while Binary Heap takes O(Logn) time.
Notes:
1) The code calculates shortest distance, but doesn’t calculate the path information. We
can create a parent array, update the parent array when distance is updated (like prim’s
implementation) and use it show the shortest path from source to different vertices.
2) The code is for undirected graph, same dijekstra function can be used for directed graphs
also.
3) The code finds shortest distances from source to all vertices. If we are interested only in
shortest distance from source to a single target, we can break the for loop when the picked
minimum distance vertex is equal to target (Step 3.a of algorithm).
4) Dijkstra’s algorithm doesn’t work for graphs with negative weight edges. For graphs with
negative weight edges, Bellman–Ford algorithm can be used, we will soon be discussing it
as a separate post.
Printing Paths in Dijkstra’s Shortest Path Algorithm
Dijkstra’s shortest path algorithm using set in STL
References:
Introduction to Algorithms by Clifford Stein, Thomas H. Cormen, Charles E. Leiserson,
Ronald L.
Algorithms by Sanjoy Dasgupta, Christos Papadimitriou, Umesh Vazirani
Source
https://www.geeksforgeeks.org/dijkstras-algorithm-for-adjacency-list-representation-greedy-algo-8/
213
Chapter 23
Below is the idea behind above algorithm (The idea is same as Prim’s MST algorithm).
A spanning tree means all vertices must be connected. So the two disjoint subsets (discussed
above) of vertices must be connected to make a Spanning Tree. And they must be connected
with the minimum weight edge to make it a Minimum Spanning Tree.
Let us understand the algorithm with below example.
214
Chapter 23. Greedy Algorithms Set 9 (Boruvka’s algorithm)
Initially MST is empty. Every vertex is singe component as highlighted in blue color in
below diagram.
For every component, find the cheapest edge that connects it to some other component.
The cheapest edges are highlighted with green color. Now MST becomes {0-1, 2-8, 2-3, 3-4,
5-6, 6-7}.
215
Chapter 23. Greedy Algorithms Set 9 (Boruvka’s algorithm)
After above step, components are {{0,1}, {2,3,4,8}, {5,6,7}}. The components are encircled
with blue color.
We again repeat the step, i.e., for every component, find the cheapest edge that connects it
to some other component.
The cheapest edges are highlighted with green color. Now MST becomes {0-1, 2-8, 2-3, 3-4,
5-6, 6-7, 1-2, 2-5}
At this stage, there is only one component {0, 1, 2, 3, 4, 5, 6, 7, 8} which has all edges.
Since there is only one component left, we stop and return MST.
Implementation:
Below is implementation of above algorithm. The input graph is represented as a collection
of edges and union-find data structure is used to keep track of components.
C/C++
216
Chapter 23. Greedy Algorithms Set 9 (Boruvka’s algorithm)
struct Edge
{
int src, dest, weight;
};
// a structure to represent a connected, undirected
// and weighted graph as a collection of edges.
struct Graph
{
// V-> Number of vertices, E-> Number of edges
int V, E;
// graph is represented as an array of edges.
// Since the graph is undirected, the edge
// from src to dest is also edge from dest
// to src. Both are counted as 1 edge here.
Edge* edge;
};
// A structure to represent a subset for union-find
struct subset
{
int parent;
int rank;
};
// Function prototypes for union-find (These functions are defined
// after boruvkaMST() )
int find(struct subset subsets[], int i);
void Union(struct subset subsets[], int x, int y);
// The main function for MST using Boruvka's algorithm
void boruvkaMST(struct Graph* graph)
{
// Get data of given graph
int V = graph->V, E = graph->E;
Edge *edge = graph->edge;
// Allocate memory for creating V subsets.
struct subset *subsets = new subset[V];
// An array to store index of the cheapest edge of
// subset. The stored index for indexing array 'edge[]'
int *cheapest = new int[V];
// Create V subsets with single elements
for (int v = 0; v < V; ++v)
{
217
Chapter 23. Greedy Algorithms Set 9 (Boruvka’s algorithm)
subsets[v].parent = v;
subsets[v].rank = 0;
cheapest[v] = -1;
}
// Initially there are V different trees.
// Finally there will be one tree that will be MST
int numTrees = V;
int MSTweight = 0;
// Keep combining components (or sets) until all
// compnentes are not combined into single MST.
while (numTrees > 1)
{
// Everytime initialize cheapest array
for (int v = 0; v < V; ++v)
{
cheapest[v] = -1;
}
// Traverse through all edges and update
// cheapest of every component
for (int i=0; i<E; i++)
{
// Find components (or sets) of two corners
// of current edge
int set1 = find(subsets, edge[i].src);
int set2 = find(subsets, edge[i].dest);
// If two corners of current edge belong to
// same set, ignore current edge
if (set1 == set2)
continue;
// Else check if current edge is closer to previous
// cheapest edges of set1 and set2
else
{
if (cheapest[set1] == -1 ||
edge[cheapest[set1]].weight > edge[i].weight)
cheapest[set1] = i;
if (cheapest[set2] == -1 ||
edge[cheapest[set2]].weight > edge[i].weight)
cheapest[set2] = i;
}
}
218
Chapter 23. Greedy Algorithms Set 9 (Boruvka’s algorithm)
// Consider the above picked cheapest edges and add them
// to MST
for (int i=0; i<V; i++)
{
// Check if cheapest for current set exists
if (cheapest[i] != -1)
{
int set1 = find(subsets, edge[cheapest[i]].src);
int set2 = find(subsets, edge[cheapest[i]].dest);
if (set1 == set2)
continue;
MSTweight += edge[cheapest[i]].weight;
printf("Edge %d-%d included in MST\n",
edge[cheapest[i]].src, edge[cheapest[i]].dest);
// Do a union of set1 and set2 and decrease number
// of trees
Union(subsets, set1, set2);
numTrees--;
}
}
}
printf("Weight of MST is %d\n", MSTweight);
return;
}
// Creates a graph with V vertices and E edges
struct Graph* createGraph(int V, int E)
{
Graph* graph = new Graph;
graph->V = V;
graph->E = E;
graph->edge = new Edge[E];
return graph;
}
// A utility function to find set of an element i
// (uses path compression technique)
int find(struct subset subsets[], int i)
{
// find root and make root as parent of i
// (path compression)
if (subsets[i].parent != i)
subsets[i].parent =
find(subsets, subsets[i].parent);
219
Chapter 23. Greedy Algorithms Set 9 (Boruvka’s algorithm)
return subsets[i].parent;
}
// A function that does union of two sets of x and y
// (uses union by rank)
void Union(struct subset subsets[], int x, int y)
{
int xroot = find(subsets, x);
int yroot = find(subsets, y);
// Attach smaller rank tree under root of high
// rank tree (Union by Rank)
if (subsets[xroot].rank < subsets[yroot].rank)
subsets[xroot].parent = yroot;
else if (subsets[xroot].rank > subsets[yroot].rank)
subsets[yroot].parent = xroot;
// If ranks are same, then make one as root and
// increment its rank by one
else
{
subsets[yroot].parent = xroot;
subsets[xroot].rank++;
}
}
// Driver program to test above functions
int main()
{
/* Let us create following weighted graph
10
0--------1
| \ |
6| 5\ |15
| \ |
2--------3
4 */
int V = 4; // Number of vertices in graph
int E = 5; // Number of edges in graph
struct Graph* graph = createGraph(V, E);
// add edge 0-1
graph->edge[0].src = 0;
graph->edge[0].dest = 1;
graph->edge[0].weight = 10;
// add edge 0-2
220
Chapter 23. Greedy Algorithms Set 9 (Boruvka’s algorithm)
graph->edge[1].src = 0;
graph->edge[1].dest = 2;
graph->edge[1].weight = 6;
// add edge 0-3
graph->edge[2].src = 0;
graph->edge[2].dest = 3;
graph->edge[2].weight = 5;
// add edge 1-3
graph->edge[3].src = 1;
graph->edge[3].dest = 3;
graph->edge[3].weight = 15;
// add edge 2-3
graph->edge[4].src = 2;
graph->edge[4].dest = 3;
graph->edge[4].weight = 4;
boruvkaMST(graph);
return 0;
}
// Thanks to Anukul Chand for modifying above code.
Python
221
Chapter 23. Greedy Algorithms Set 9 (Boruvka’s algorithm)
if parent[i] == i:
return i
return self.find(parent, parent[i])
# A function that does union of two sets of x and y
# (uses union by rank)
def union(self, parent, rank, x, y):
xroot = self.find(parent, x)
yroot = self.find(parent, y)
# Attach smaller rank tree under root of high rank tree
# (Union by Rank)
if rank[xroot] < rank[yroot]:
parent[xroot] = yroot
elif rank[xroot] > rank[yroot]:
parent[yroot] = xroot
#If ranks are same, then make one as root and increment
# its rank by one
else :
parent[yroot] = xroot
rank[xroot] += 1
# The main function to construct MST using Kruskal's algorithm
def boruvkaMST(self):
parent = []; rank = [];
# An array to store index of the cheapest edge of
# subset. It store [u,v,w] for each component
cheapest =[]
# Initially there are V different trees.
# Finally there will be one tree that will be MST
numTrees = self.V
MSTweight = 0
# Create V subsets with single elements
for node in range(self.V):
parent.append(node)
rank.append(0)
cheapest =[-1] * self.V
# Keep combining components (or sets) until all
# compnentes are not combined into single MST
while numTrees > 1:
# Traverse through all edges and update
# cheapest of every component
222
Chapter 23. Greedy Algorithms Set 9 (Boruvka’s algorithm)
for i in range(len(self.graph)):
# Find components (or sets) of two corners
# of current edge
u,v,w = self.graph[i]
set1 = self.find(parent, u)
set2 = self.find(parent ,v)
# If two corners of current edge belong to
# same set, ignore current edge. Else check if
# current edge is closer to previous
# cheapest edges of set1 and set2
if set1 != set2:
if cheapest[set1] == -1 or cheapest[set1][2] > w :
cheapest[set1] = [u,v,w]
if cheapest[set2] == -1 or cheapest[set2][2] > w :
cheapest[set2] = [u,v,w]
# Consider the above picked cheapest edges and add them
# to MST
for node in range(self.V):
#Check if cheapest for current set exists
if cheapest[node] != -1:
u,v,w = cheapest[node]
set1 = self.find(parent, u)
set2 = self.find(parent ,v)
if set1 != set2 :
MSTweight += w
self.union(parent, rank, set1, set2)
print ("Edge %d-%d with weight %d included in MST" % (u,v,w))
numTrees = numTrees - 1
#reset cheapest array
cheapest =[-1] * self.V
print ("Weight of MST is %d" % MSTweight)
g = Graph(4)
g.addEdge(0, 1, 10)
g.addEdge(0, 2, 6)
g.addEdge(0, 3, 5)
223
Chapter 23. Greedy Algorithms Set 9 (Boruvka’s algorithm)
g.addEdge(1, 3, 15)
g.addEdge(2, 3, 4)
g.boruvkaMST()
#This code is contributed by Neelam Yadav
Output:
Source
https://www.geeksforgeeks.org/boruvkas-algorithm-greedy-algo-9/
224
Chapter 24
Bellman-Ford Algorithm
225
Chapter 24. Bellman-Ford Algorithm
have at-most one edge in the path. Then, it calculates shortest paths with at-most 2 edges,
and so on. After the i-th iteration of outer loop, the shortest paths with at most i edges
are calculated. There can be maximum V – 1 edges in any simple path, that is why the
outer loop runs v – 1 times. The idea is, assuming that there is no negative weight cycle,
if we have calculated shortest paths with at most i edges, then an iteration over all edges
guarantees to give shortest path with at-most (i+1) edges (Proof is simple, you can refer
this or MIT Video Lecture)
Example
Let us understand the algorithm with following example graph. The images are taken from
thissource.
Let the given source vertex be 0. Initialize all distances as infinite, except the distance to
source itself. Total number of vertices in the graph is 5, so all edges must be processed 4
times.
Let all edges are processed in following order: (B,E), (D,B), (B,D), (A,B), (A,C), (D,C),
(B,C), (E,D). We get following distances when all edges are processed first time. The first
row in shows initial distances. The second row shows distances when edges (B,E), (D,B),
(B,D) and (A,B) are processed. The third row shows distances when (A,C) is processed.
The fourth row shows when (D,C), (B,C) and (E,D) are processed.
226
Chapter 24. Bellman-Ford Algorithm
The first iteration guarantees to give all shortest paths which are at most 1 edge long. We
get following distances when all edges are processed second time (The last row shows final
values).
The second iteration guarantees to give all shortest paths which are at most 2 edges long.
The algorithm processes all edges 2 more times. The distances are minimized after the
second iteration, so third and fourth iterations don’t update the distances.
Implementation:
C++
227
Chapter 24. Bellman-Ford Algorithm
228
Chapter 24. Bellman-Ford Algorithm
// as INFINITE
for (int i = 0; i < V; i++)
dist[i] = INT_MAX;
dist[src] = 0;
// Step 2: Relax all edges |V| - 1 times. A simple shortest
// path from src to any other vertex can have at-most |V| - 1
// edges
for (int i = 1; i <= V-1; i++)
{
for (int j = 0; j < E; j++)
{
int u = graph->edge[j].src;
int v = graph->edge[j].dest;
int weight = graph->edge[j].weight;
if (dist[u] != INT_MAX && dist[u] + weight < dist[v])
dist[v] = dist[u] + weight;
}
}
// Step 3: check for negative-weight cycles. The above step
// guarantees shortest distances if graph doesn't contain
// negative weight cycle. If we get a shorter path, then there
// is a cycle.
for (int i = 0; i < E; i++)
{
int u = graph->edge[i].src;
int v = graph->edge[i].dest;
int weight = graph->edge[i].weight;
if (dist[u] != INT_MAX && dist[u] + weight < dist[v])
printf("Graph contains negative weight cycle");
}
printArr(dist, V);
return;
}
// Driver program to test above functions
int main()
{
/* Let us create the graph given in above example */
int V = 5; // Number of vertices in graph
int E = 8; // Number of edges in graph
struct Graph* graph = createGraph(V, E);
// add edge 0-1 (or A-B in above figure)
graph->edge[0].src = 0;
229
Chapter 24. Bellman-Ford Algorithm
graph->edge[0].dest = 1;
graph->edge[0].weight = -1;
// add edge 0-2 (or A-C in above figure)
graph->edge[1].src = 0;
graph->edge[1].dest = 2;
graph->edge[1].weight = 4;
// add edge 1-2 (or B-C in above figure)
graph->edge[2].src = 1;
graph->edge[2].dest = 2;
graph->edge[2].weight = 3;
// add edge 1-3 (or B-D in above figure)
graph->edge[3].src = 1;
graph->edge[3].dest = 3;
graph->edge[3].weight = 2;
// add edge 1-4 (or A-E in above figure)
graph->edge[4].src = 1;
graph->edge[4].dest = 4;
graph->edge[4].weight = 2;
// add edge 3-2 (or D-C in above figure)
graph->edge[5].src = 3;
graph->edge[5].dest = 2;
graph->edge[5].weight = 5;
// add edge 3-1 (or D-B in above figure)
graph->edge[6].src = 3;
graph->edge[6].dest = 1;
graph->edge[6].weight = 1;
// add edge 4-3 (or E-D in above figure)
graph->edge[7].src = 4;
graph->edge[7].dest = 3;
graph->edge[7].weight = -3;
BellmanFord(graph, 0);
return 0;
}
Java
230
Chapter 24. Bellman-Ford Algorithm
import java.lang.*;
import java.io.*;
// A class to represent a connected, directed and weighted graph
class Graph
{
// A class to represent a weighted edge in graph
class Edge {
int src, dest, weight;
Edge() {
src = dest = weight = 0;
}
};
int V, E;
Edge edge[];
// Creates a graph with V vertices and E edges
Graph(int v, int e)
{
V = v;
E = e;
edge = new Edge[e];
for (int i=0; i<e; ++i)
edge[i] = new Edge();
}
// The main function that finds shortest distances from src
// to all other vertices using Bellman-Ford algorithm. The
// function also detects negative weight cycle
void BellmanFord(Graph graph,int src)
{
int V = graph.V, E = graph.E;
int dist[] = new int[V];
// Step 1: Initialize distances from src to all other
// vertices as INFINITE
for (int i=0; i<V; ++i)
dist[i] = Integer.MAX_VALUE;
dist[src] = 0;
// Step 2: Relax all edges |V| - 1 times. A simple
// shortest path from src to any other vertex can
// have at-most |V| - 1 edges
for (int i=1; i<V; ++i)
{
for (int j=0; j<E; ++j)
{
231
Chapter 24. Bellman-Ford Algorithm
int u = graph.edge[j].src;
int v = graph.edge[j].dest;
int weight = graph.edge[j].weight;
if (dist[u]!=Integer.MAX_VALUE &&
dist[u]+weight<dist[v])
dist[v]=dist[u]+weight;
}
}
// Step 3: check for negative-weight cycles. The above
// step guarantees shortest distances if graph doesn't
// contain negative weight cycle. If we get a shorter
// path, then there is a cycle.
for (int j=0; j<E; ++j)
{
int u = graph.edge[j].src;
int v = graph.edge[j].dest;
int weight = graph.edge[j].weight;
if (dist[u] != Integer.MAX_VALUE &&
dist[u]+weight < dist[v])
System.out.println("Graph contains negative weight cycle");
}
printArr(dist, V);
}
// A utility function used to print the solution
void printArr(int dist[], int V)
{
System.out.println("Vertex Distance from Source");
for (int i=0; i<V; ++i)
System.out.println(i+"\t\t"+dist[i]);
}
// Driver method to test above function
public static void main(String[] args)
{
int V = 5; // Number of vertices in graph
int E = 8; // Number of edges in graph
Graph graph = new Graph(V, E);
// add edge 0-1 (or A-B in above figure)
graph.edge[0].src = 0;
graph.edge[0].dest = 1;
graph.edge[0].weight = -1;
// add edge 0-2 (or A-C in above figure)
graph.edge[1].src = 0;
232
Chapter 24. Bellman-Ford Algorithm
graph.edge[1].dest = 2;
graph.edge[1].weight = 4;
// add edge 1-2 (or B-C in above figure)
graph.edge[2].src = 1;
graph.edge[2].dest = 2;
graph.edge[2].weight = 3;
// add edge 1-3 (or B-D in above figure)
graph.edge[3].src = 1;
graph.edge[3].dest = 3;
graph.edge[3].weight = 2;
// add edge 1-4 (or A-E in above figure)
graph.edge[4].src = 1;
graph.edge[4].dest = 4;
graph.edge[4].weight = 2;
// add edge 3-2 (or D-C in above figure)
graph.edge[5].src = 3;
graph.edge[5].dest = 2;
graph.edge[5].weight = 5;
// add edge 3-1 (or D-B in above figure)
graph.edge[6].src = 3;
graph.edge[6].dest = 1;
graph.edge[6].weight = 1;
// add edge 4-3 (or E-D in above figure)
graph.edge[7].src = 4;
graph.edge[7].dest = 3;
graph.edge[7].weight = -3;
graph.BellmanFord(graph, 0);
}
}
// Contributed by Aakash Hasija
Python
233
Chapter 24. Bellman-Ford Algorithm
def __init__(self,vertices):
self.V= vertices #No. of vertices
self.graph = [] # default dictionary to store graph
# function to add an edge to graph
def addEdge(self,u,v,w):
self.graph.append([u, v, w])
# utility function used to print the solution
def printArr(self, dist):
print("Vertex Distance from Source")
for i in range(self.V):
print("%d \t\t %d" % (i, dist[i]))
# The main function that finds shortest distances from src to
# all other vertices using Bellman-Ford algorithm. The function
# also detects negative weight cycle
def BellmanFord(self, src):
# Step 1: Initialize distances from src to all other vertices
# as INFINITE
dist = [float("Inf")] * self.V
dist[src] = 0
# Step 2: Relax all edges |V| - 1 times. A simple shortest
# path from src to any other vertex can have at-most |V| - 1
# edges
for i in range(self.V - 1):
# Update dist value and parent index of the adjacent vertices of
# the picked vertex. Consider only those vertices which are still in
# queue
for u, v, w in self.graph:
if dist[u] != float("Inf") and dist[u] + w < dist[v]:
dist[v] = dist[u] + w
# Step 3: check for negative-weight cycles. The above step
# guarantees shortest distances if graph doesn't contain
# negative weight cycle. If we get a shorter path, then there
# is a cycle.
for u, v, w in self.graph:
if dist[u] != float("Inf") and dist[u] + w < dist[v]:
print "Graph contains negative weight cycle"
return
# print all distance
self.printArr(dist)
234
Chapter 24. Bellman-Ford Algorithm
g = Graph(5)
g.addEdge(0, 1, -1)
g.addEdge(0, 2, 4)
g.addEdge(1, 2, 3)
g.addEdge(1, 3, 2)
g.addEdge(1, 4, 2)
g.addEdge(3, 2, 5)
g.addEdge(3, 1, 1)
g.addEdge(4, 3, -3)
#Print the solution
g.BellmanFord(0)
#This code is contributed by Neelam Yadav
Output:
Notes
1) Negative weights are found in various applications of graphs. For example, instead of
paying cost for a path, we may get some advantage if we follow the path.
2) Bellman-Ford works better (better than Dijksra’s) for distributed systems. Unlike Di-
jksra’s where we need to find minimum value of all vertices, in Bellman-Ford, edges are
considered one by one.
Exercise
1) The standard Bellman-Ford algorithm reports shortest path only if there is no negative
weight cycles. Modify it so that it reports minimum distances even if there is a negative
weight cycle.
2) Can we use Dijksra’s algorithm for shortest paths for graphs with negative weights – one
idea can be, calculate the minimum weight value, add a positive value (equal to absolute
value of minimum weight value) to all weights and run the Dijksra’s algorithm for the
modified graph. Will this algorithm work?
References:
http://www.youtube.com/watch?v=Ttezuzs39nk
http://en.wikipedia.org/wiki/Bellman%E2%80%93Ford_algorithm
http://www.cs.arizona.edu/classes/cs445/spring07/ShortestPath2.prn.pdf
235
Chapter 24. Bellman-Ford Algorithm
Source
https://www.geeksforgeeks.org/bellman-ford-algorithm-dp-23/
236
Chapter 25
Input:
graph[][] = { {0, 5, INF, 10},
{INF, 0, 3, INF},
{INF, INF, 0, 1},
{INF, INF, INF, 0} }
which represents the following graph
10
(0)------->(3)
| /|\
5 | |
| | 1
\|/ |
(1)------->(2)
3
Note that the value of graph[i][j] is 0 if i is equal to j
And graph[i][j] is INF (infinite) if there is no edge from vertex i to j.
Output:
Shortest distance matrix
0 5 8 9
INF 0 3 4
INF INF 0 1
INF INF INF 0
237
Chapter 25. Floyd Warshall Algorithm
238
Chapter 25. Floyd Warshall Algorithm
239
Chapter 25. Floyd Warshall Algorithm
Java
240
Chapter 25. Floyd Warshall Algorithm
/* Add all vertices one by one to the set of intermediate
vertices.
---> Before start of an iteration, we have shortest
distances between all pairs of vertices such that
the shortest distances consider only the vertices in
set {0, 1, 2, .. k-1} as intermediate vertices.
----> After the end of an iteration, vertex no. k is added
to the set of intermediate vertices and the set
becomes {0, 1, 2, .. k} */
for (k = 0; k < V; k++)
{
// Pick all vertices as source one by one
for (i = 0; i < V; i++)
{
// Pick all vertices as destination for the
// above picked source
for (j = 0; j < V; j++)
{
// If vertex k is on the shortest path from
// i to j, then update the value of dist[i][j]
if (dist[i][k] + dist[k][j] < dist[i][j])
dist[i][j] = dist[i][k] + dist[k][j];
}
}
}
// Print the shortest distance matrix
printSolution(dist);
}
void printSolution(int dist[][])
{
System.out.println("The following matrix shows the shortest "+
"distances between every pair of vertices");
for (int i=0; i<V; ++i)
{
for (int j=0; j<V; ++j)
{
if (dist[i][j]==INF)
System.out.print("INF ");
else
System.out.print(dist[i][j]+" ");
}
System.out.println();
}
}
241
Chapter 25. Floyd Warshall Algorithm
Python
242
Chapter 25. Floyd Warshall Algorithm
243
Chapter 25. Floyd Warshall Algorithm
5 | |
| | 1
\|/ |
(1)------->(2)
3 """
graph = [[0,5,INF,10],
[INF,0,3,INF],
[INF, INF, 0, 1],
[INF, INF, INF, 0]
]
# Print the solution
floydWarshall(graph);
# This code is contributed by Nikhil Kumar Singh(nickzuck_007)
C#
244
Chapter 25. Floyd Warshall Algorithm
245
Chapter 25. Floyd Warshall Algorithm
Console.WriteLine();
}
}
// Driver Code
public static void Main(string[] args)
{
/* Let us create the following
weighted graph
10
(0)------->(3)
| /|\
5 | |
| | 1
\|/ |
(1)------->(2)
3 */
int[,] graph = { {0, 5, INF, 10},
{INF, 0, 3, INF},
{INF, INF, 0, 1},
{INF, INF, INF, 0}
};
AllPairShortestPath a = new AllPairShortestPath();
// Print the solution
a.floydWarshall(graph);
}
}
// This article is contributed by
// Abdul Mateen Mohammed
Output:
Following matrix shows the shortest distances between every pair of vertices
0 5 8 9
INF 0 3 4
INF INF 0 1
INF INF INF 0
246
Chapter 25. Floyd Warshall Algorithm
handle maximum possible value. When we take INF as INT_MAX, we need to change the
if condition in the above program to avoid arithmetic overflow.
#include
Source
https://www.geeksforgeeks.org/floyd-warshall-algorithm-dp-16/
247
Chapter 26
248
Chapter 26. Johnson’s algorithm for All-pairs shortest paths
Algorithm:
1) Let the given graph be G. Add a new vertex s to the graph, add edges from new vertex
to all vertices of G. Let the modified graph be G’.
2) Run Bellman-Ford algorithm on G’ with s as source. Let the distances calculated by
Bellman-Ford be h[0], h[1], .. h[V-1]. If we find a negative weight cycle, then return. Note
that the negative weight cycle cannot be created by new vertex s as there is no edge to s.
All edges are from s.
3) Reweight the edges of original graph. For each edge (u, v), assign the new weight as
“original weight + h[u] – h[v]”.
4) Remove the added vertex s and run Dijkstra’s algorithm for every vertex.
How does the transformation ensure nonnegative weight edges?
The following property is always true about h[] values as they are shortest distances.
The property simply means, shortest distance from s to v must be smaller than or equal to
shortest distance from s to u plus weight of edge (u, v). The new weights are w(u, v) + h[u]
- h[v]. The value of the new weights must be greater than or equal to zero because of the
inequality ”h[v] <= h[u] + w(u, v)”. Example:
Let us consider the following graph.
We add a source s and add edges from s to all vertices of the original graph. In the following
diagram s is 4.
249
Chapter 26. Johnson’s algorithm for All-pairs shortest paths
We calculate the shortest distances from 4 to all other vertices using Bellman-Ford algorithm.
The shortest distances from 4 to 0, 1, 2 and 3 are 0, -5, -1 and 0 respectively, i.e., h[] =
{0, -5, -1, 0}. Once we get these distances, we remove the source vertex 4 and reweight the
edges using following formula. w(u, v) = w(u, v) + h[u] - h[v].
Since all weights are positive now, we can run Dijkstra’s shortest path algorithm for every
vertex as source.
Time Complexity: The main steps in algorithm are Bellman Ford Algorithm called once
and Dijkstra called V times. Time complexity of Bellman Ford is O(VE) and time complexity
of Dijkstra is O(VLogV). So overall time complexity is O(V2 log V + VE).
The time complexity of Johnson’s algorithm becomes same as Floyd Warshellwhen the
graphs is complete (For a complete graph E = O(V2 ). But for sparse graphs, the algorithm
performs much better than Floyd Warshell.
References:
Introduction to Algorithms 3rd Edition by Clifford Stein, Thomas H. Cormen, Charles E.
Leiserson, Ronald L. Rivest
http://www.youtube.com/watch?v=b6LOHvCzmkI
http://www.youtube.com/watch?v=TV2Z6nbo1ic
http://en.wikipedia.org/wiki/Johnson%27s_algorithm
http://www.youtube.com/watch?v=Sygq1e0xWnM
Source
https://www.geeksforgeeks.org/johnsons-algorithm/
250
Chapter 27
251
Chapter 27. Shortest Path in Directed Acyclic Graph
252
Chapter 27. Shortest Path in Directed Acyclic Graph
// C++ program to find single source shortest paths for Directed Acyclic Graphs
#include<iostream>
#include <list>
#include <stack>
#include <limits.h>
#define INF INT_MAX
using namespace std;
// Graph is represented using adjacency list. Every node of adjacency list
// contains vertex number of the vertex to which edge connects. It also
// contains weight of the edge
class AdjListNode
{
int v;
int weight;
public:
AdjListNode(int _v, int _w) { v = _v; weight = _w;}
int getV() { return v; }
int getWeight() { return weight; }
};
// Class to represent a graph using adjacency list representation
class Graph
{
int V; // No. of vertices'
// Pointer to an array containing adjacency lists
list<AdjListNode> *adj;
// A function used by shortestPath
void topologicalSortUtil(int v, bool visited[], stack<int> &Stack);
public:
Graph(int V); // Constructor
// function to add an edge to graph
void addEdge(int u, int v, int weight);
// Finds shortest paths from given source vertex
void shortestPath(int s);
};
Graph::Graph(int V)
{
this->V = V;
adj = new list<AdjListNode>[V];
253
Chapter 27. Shortest Path in Directed Acyclic Graph
}
void Graph::addEdge(int u, int v, int weight)
{
AdjListNode node(v, weight);
adj[u].push_back(node); // Add v to u's list
}
// A recursive function used by shortestPath. See below link for details
// https://www.geeksforgeeks.org/topological-sorting/
void Graph::topologicalSortUtil(int v, bool visited[], stack<int> &Stack)
{
// Mark the current node as visited
visited[v] = true;
// Recur for all the vertices adjacent to this vertex
list<AdjListNode>::iterator i;
for (i = adj[v].begin(); i != adj[v].end(); ++i)
{
AdjListNode node = *i;
if (!visited[node.getV()])
topologicalSortUtil(node.getV(), visited, Stack);
}
// Push current vertex to stack which stores topological sort
Stack.push(v);
}
// The function to find shortest paths from given vertex. It uses recursive
// topologicalSortUtil() to get topological sorting of given graph.
void Graph::shortestPath(int s)
{
stack<int> Stack;
int dist[V];
// Mark all the vertices as not visited
bool *visited = new bool[V];
for (int i = 0; i < V; i++)
visited[i] = false;
// Call the recursive helper function to store Topological Sort
// starting from all vertices one by one
for (int i = 0; i < V; i++)
if (visited[i] == false)
topologicalSortUtil(i, visited, Stack);
// Initialize distances to all vertices as infinite and distance
// to source as 0
254
Chapter 27. Shortest Path in Directed Acyclic Graph
255
Chapter 27. Shortest Path in Directed Acyclic Graph
Java
// Java program to find single source shortest paths in Directed Acyclic Graphs
import java.io.*;
import java.util.*;
class ShortestPath
{
static final int INF=Integer.MAX_VALUE;
class AdjListNode
{
private int v;
private int weight;
AdjListNode(int _v, int _w) { v = _v; weight = _w; }
int getV() { return v; }
int getWeight() { return weight; }
}
// Class to represent graph as an adjcency list of
// nodes of type AdjListNode
class Graph
{
private int V;
private LinkedList<AdjListNode>adj[];
Graph(int v)
{
V=v;
adj = new LinkedList[V];
for (int i=0; i<v; ++i)
adj[i] = new LinkedList<AdjListNode>();
}
void addEdge(int u, int v, int weight)
{
AdjListNode node = new AdjListNode(v,weight);
adj[u].add(node);// Add v to u's list
}
// A recursive function used by shortestPath.
// See below link for details
void topologicalSortUtil(int v, Boolean visited[], Stack stack)
{
// Mark the current node as visited.
visited[v] = true;
Integer i;
// Recur for all the vertices adjacent to this vertex
256
Chapter 27. Shortest Path in Directed Acyclic Graph
Iterator<AdjListNode> it = adj[v].iterator();
while (it.hasNext())
{
AdjListNode node =it.next();
if (!visited[node.getV()])
topologicalSortUtil(node.getV(), visited, stack);
}
// Push current vertex to stack which stores result
stack.push(new Integer(v));
}
// The function to find shortest paths from given vertex. It
// uses recursive topologicalSortUtil() to get topological
// sorting of given graph.
void shortestPath(int s)
{
Stack stack = new Stack();
int dist[] = new int[V];
// Mark all the vertices as not visited
Boolean visited[] = new Boolean[V];
for (int i = 0; i < V; i++)
visited[i] = false;
// Call the recursive helper function to store Topological
// Sort starting from all vertices one by one
for (int i = 0; i < V; i++)
if (visited[i] == false)
topologicalSortUtil(i, visited, stack);
// Initialize distances to all vertices as infinite and
// distance to source as 0
for (int i = 0; i < V; i++)
dist[i] = INF;
dist[s] = 0;
// Process vertices in topological order
while (stack.empty() == false)
{
// Get the next vertex from topological order
int u = (int)stack.pop();
// Update distances of all adjacent vertices
Iterator<AdjListNode> it;
if (dist[u] != INF)
{
it = adj[u].iterator();
while (it.hasNext())
257
Chapter 27. Shortest Path in Directed Acyclic Graph
{
AdjListNode i= it.next();
if (dist[i.getV()] > dist[u] + i.getWeight())
dist[i.getV()] = dist[u] + i.getWeight();
}
}
}
// Print the calculated shortest distances
for (int i = 0; i < V; i++)
{
if (dist[i] == INF)
System.out.print( "INF ");
else
System.out.print( dist[i] + " ");
}
}
}
// Method to create a new graph instance through an object
// of ShortestPath class.
Graph newGraph(int number)
{
return new Graph(number);
}
public static void main(String args[])
{
// Create a graph given in the above diagram. Here vertex
// numbers are 0, 1, 2, 3, 4, 5 with following mappings:
// 0=r, 1=s, 2=t, 3=x, 4=y, 5=z
ShortestPath t = new ShortestPath();
Graph g = t.newGraph(6);
g.addEdge(0, 1, 5);
g.addEdge(0, 2, 3);
g.addEdge(1, 3, 6);
g.addEdge(1, 2, 2);
g.addEdge(2, 4, 4);
g.addEdge(2, 5, 2);
g.addEdge(2, 3, 7);
g.addEdge(3, 4, -1);
g.addEdge(4, 5, -2);
int s = 1;
System.out.println("Following are shortest distances "+
"from source " + s );
g.shortestPath(s);
}
258
Chapter 27. Shortest Path in Directed Acyclic Graph
}
//This code is contributed by Aakash Hasija
Python
259
Chapter 27. Shortest Path in Directed Acyclic Graph
visited = [False]*self.V
stack =[]
# Call the recursive helper function to store Topological
# Sort starting from source vertice
for i in range(self.V):
if visited[i] == False:
self.topologicalSortUtil(s,visited,stack)
# Initialize distances to all vertices as infinite and
# distance to source as 0
dist = [float("Inf")] * (self.V)
dist[s] = 0
# Process vertices in topological order
while stack:
# Get the next vertex from topological order
i = stack.pop()
# Update distances of all adjacent vertices
for node,weight in self.graph[i]:
if dist[node] > dist[i] + weight:
dist[node] = dist[i] + weight
# Print the calculated shortest distances
for i in range(self.V):
print ("%d" %dist[i]) if dist[i] != float("Inf") else "Inf" ,
g = Graph(6)
g.addEdge(0, 1, 5)
g.addEdge(0, 2, 3)
g.addEdge(1, 3, 6)
g.addEdge(1, 2, 2)
g.addEdge(2, 4, 4)
g.addEdge(2, 5, 2)
g.addEdge(2, 3, 7)
g.addEdge(3, 4, -1)
g.addEdge(4, 5, -2)
# source = 1
s = 1
print ("Following are shortest distances from source %d " % s)
g.shortestPath(s)
# This code is contributed by Neelam Yadav
260
Chapter 27. Shortest Path in Directed Acyclic Graph
Output:
Time Complexity: Time complexity of topological sorting is O(V+E). After finding topo-
logical order, the algorithm process all vertices and for every vertex, it runs a loop for all
adjacent vertices. Total adjacent vertices in a graph is O(E). So the inner loop runs O(V+E)
times. Therefore, overall time complexity of this algorithm is O(V+E).
References:
http://www.utdallas.edu/~sizheng/CS4349.d/l-notes.d/L17.pdf
Source
https://www.geeksforgeeks.org/shortest-path-for-directed-acyclic-graphs/
261
Chapter 28
262
Chapter 28. Some interesting shortest path questions,
Question 4: Given a directed acyclic weighted graph, how to find the shortest
path from a source s to a destination t in O(V+E) time?
See: Shortest Path in Directed Acyclic Graph
More Questions See following links for more questions.
http://algs4.cs.princeton.edu/44sp/
https://www.geeksforgeeks.org/algorithms-gq/graph-shortest-paths-gq/
Source
https://www.geeksforgeeks.org/interesting-shortest-path-questions-set-1/
263
Chapter 29
Shortest path with exactly k edges in a directed and weighted graph - GeeksforGeeks
Given a directed and two vertices ‘u’ and ‘v’ in it, find shortest path from ‘u’ to ‘v’ with
exactly k edges on the path.
The graph is given as adjacency matrix representation where value of graph[i][j] indicates
the weight of an edge from vertex i to vertex j and a value INF(infinite) indicates no edge
from i to j.
For example consider the following graph. Let source ‘u’ be vertex 0, destination ‘v’ be 3
and k be 2. There are two walks of length 2, the walks are {0, 2, 3} and {0, 1, 3}. The
shortest among the two is {0, 2, 3} and weight of path is 3+6 = 9.
The idea is to browse through all paths of length k from u to v using the approach discussed
in the previous post and return weight of the shortest path. A simple solution is to start
264
Chapter 29. Shortest path with exactly k edges in a directed and weighted graph
from u, go to all adjacent vertices and recur for adjacent vertices with k as k-1, source as
adjacent vertex and destination as v. Following are C++ and Java implementations of this
simple solution.
C++
265
Chapter 29. Shortest path with exactly k edges in a directed and weighted graph
Java
266
Chapter 29. Shortest path with exactly k edges in a directed and weighted graph
Output:
The worst case time complexity of the above function is O(Vk ) where V is the number of
vertices in the given graph. We can simply analyze the time complexity by drawing recursion
tree. The worst occurs for a complete graph. In worst case, every internal node of recursion
tree would have exactly V children.
We can optimize the above solution using Dynamic Programming. The idea is to build
a 3D table where first dimension is source, second dimension is destination, third dimension
is number of edges from source to destination, and the value is count of walks. Like other
Dynamic Programming problems, we fill the 3D table in bottom up manner.
C++
267
Chapter 29. Shortest path with exactly k edges in a directed and weighted graph
{
for (int j = 0; j < V; j++) // for destination
{
// initialize value
sp[i][j][e] = INF;
// from base cases
if (e == 0 && i == j)
sp[i][j][e] = 0;
if (e == 1 && graph[i][j] != INF)
sp[i][j][e] = graph[i][j];
//go to adjacent only when number of edges is more than 1
if (e > 1)
{
for (int a = 0; a < V; a++)
{
// There should be an edge from i to a and a
// should not be same as either i or j
if (graph[i][a] != INF && i != a &&
j!= a && sp[a][j][e-1] != INF)
sp[i][j][e] = min(sp[i][j][e], graph[i][a] +
sp[a][j][e-1]);
}
}
}
}
}
return sp[u][v][k];
}
// driver program to test above function
int main()
{
/* Let us create the graph shown in above diagram*/
int graph[V][V] = { {0, 10, 3, 2},
{INF, 0, INF, 7},
{INF, INF, 0, 6},
{INF, INF, INF, 0}
};
int u = 0, v = 3, k = 2;
cout << shortestPath(graph, u, v, k);
return 0;
}
Java
268
Chapter 29. Shortest path with exactly k edges in a directed and weighted graph
// exactly k edges
import java.util.*;
import java.lang.*;
import java.io.*;
class ShortestPath
{
// Define number of vertices in the graph and inifinite value
static final int V = 4;
static final int INF = Integer.MAX_VALUE;
// A Dynamic programming based function to find the shortest path
// from u to v with exactly k edges.
int shortestPath(int graph[][], int u, int v, int k)
{
// Table to be filled up using DP. The value sp[i][j][e] will
// store weight of the shortest path from i to j with exactly
// k edges
int sp[][][] = new int[V][V][k+1];
// Loop for number of edges from 0 to k
for (int e = 0; e <= k; e++)
{
for (int i = 0; i < V; i++) // for source
{
for (int j = 0; j < V; j++) // for destination
{
// initialize value
sp[i][j][e] = INF;
// from base cases
if (e == 0 && i == j)
sp[i][j][e] = 0;
if (e == 1 && graph[i][j] != INF)
sp[i][j][e] = graph[i][j];
// go to adjacent only when number of edges is
// more than 1
if (e > 1)
{
for (int a = 0; a < V; a++)
{
// There should be an edge from i to a and
// a should not be same as either i or j
if (graph[i][a] != INF && i != a &&
j!= a && sp[a][j][e-1] != INF)
sp[i][j][e] = Math.min(sp[i][j][e],
graph[i][a] + sp[a][j][e-1]);
269
Chapter 29. Shortest path with exactly k edges in a directed and weighted graph
}
}
}
}
}
return sp[u][v][k];
}
public static void main (String[] args)
{
/* Let us create the graph shown in above diagram*/
int graph[][] = new int[][]{ {0, 10, 3, 2},
{INF, 0, INF, 7},
{INF, INF, 0, 6},
{INF, INF, INF, 0}
};
ShortestPath t = new ShortestPath();
int u = 0, v = 3, k = 2;
System.out.println("Weight of the shortest path is "+
t.shortestPath(graph, u, v, k));
}
}
//This code is contributed by Aakash Hasija
Output:
Time complexity of the above DP based solution is O(V3 K) which is much better than the
naive solution.
This article is contributed by Abhishek. Please write comments if you find anything
incorrect, or you want to share more information about the topic discussed above
Source
https://www.geeksforgeeks.org/shortest-path-exactly-k-edges-directed-weighted-graph/
270
Chapter 30
We can either use Breadth First Search (BFS) or Depth First Search (DFS) to find path
between two vertices. Take the first vertex as source in BFS (or DFS), follow the standard
BFS (or DFS). If we see the second vertex in our traversal, then return true. Else return
false.
Following are C++,Java and Python codes that use BFS for finding reachability of second
vertex from first vertex.
C++
271
Chapter 30. Find if there is a path between two vertices in a directed graph
272
Chapter 30. Find if there is a path between two vertices in a directed graph
s = queue.front();
queue.pop_front();
// Get all adjacent vertices of the dequeued vertex s
// If a adjacent has not been visited, then mark it visited
// and enqueue it
for (i = adj[s].begin(); i != adj[s].end(); ++i)
{
// If this adjacent node is the destination node, then
// return true
if (*i == d)
return true;
// Else, continue to do BFS
if (!visited[*i])
{
visited[*i] = true;
queue.push_back(*i);
}
}
}
// If BFS is complete without visiting d
return false;
}
// Driver program to test methods of graph class
int main()
{
// Create a graph given in the above diagram
Graph g(4);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 2);
g.addEdge(2, 0);
g.addEdge(2, 3);
g.addEdge(3, 3);
int u = 1, v = 3;
if(g.isReachable(u, v))
cout<< "\n There is a path from " << u << " to " << v;
else
cout<< "\n There is no path from " << u << " to " << v;
u = 3, v = 1;
if(g.isReachable(u, v))
cout<< "\n There is a path from " << u << " to " << v;
else
273
Chapter 30. Find if there is a path between two vertices in a directed graph
cout<< "\n There is no path from " << u << " to " << v;
return 0;
}
Java
274
Chapter 30. Find if there is a path between two vertices in a directed graph
275
Chapter 30. Find if there is a path between two vertices in a directed graph
int v = 3;
if (g.isReachable(u, v))
System.out.println("There is a path from " + u +" to " + v);
else
System.out.println("There is no path from " + u +" to " + v);;
u = 3;
v = 1;
if (g.isReachable(u, v))
System.out.println("There is a path from " + u +" to " + v);
else
System.out.println("There is no path from " + u +" to " + v);;
}
}
// This code is contributed by Aakash Hasija
Python
276
Chapter 30. Find if there is a path between two vertices in a directed graph
Output:
As an exercise, try an extended version of the problem where the complete path between
two vertices is also needed.
277
Chapter 30. Find if there is a path between two vertices in a directed graph
Source
https://www.geeksforgeeks.org/find-if-there-is-a-path-between-two-vertices-in-a-given-graph/
278
Chapter 31
279
Chapter 31. Find if the strings can be chained to form a circle
The idea is to create a directed graph of all characters and then find if their is an eulerian
circuit in the graph or not.
Graph representation of some string arrays are given in below diagram,
280
Chapter 31. Find if the strings can be chained to form a circle
// A class that represents an undirected graph
class Graph
{
int V; // No. of vertices
list<int> *adj; // A dynamic array of adjacency lists
int *in;
public:
// Constructor and destructor
Graph(int V);
~Graph() { delete [] adj; delete [] in; }
// function to add an edge to graph
void addEdge(int v, int w) { adj[v].push_back(w); (in[w])++; }
// Method to check if this graph is Eulerian or not
bool isEulerianCycle();
// Method to check if all non-zero degree vertices are connected
bool isSC();
// Function to do DFS starting from v. Used in isConnected();
void DFSUtil(int v, bool visited[]);
Graph getTranspose();
};
Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V];
in = new int[V];
for (int i = 0; i < V; i++)
in[i] = 0;
}
/* This function returns true if the directed graph has an eulerian
cycle, otherwise returns false */
bool Graph::isEulerianCycle()
{
// Check if all non-zero degree vertices are connected
if (isSC() == false)
return false;
// Check if in degree and out degree of every vertex is same
for (int i = 0; i < V; i++)
if (adj[i].size() != in[i])
return false;
281
Chapter 31. Find if the strings can be chained to form a circle
return true;
}
// A recursive function to do DFS starting from v
void Graph::DFSUtil(int v, bool visited[])
{
// Mark the current node as visited and print it
visited[v] = true;
// Recur for all the vertices adjacent to this vertex
list<int>::iterator i;
for (i = adj[v].begin(); i != adj[v].end(); ++i)
if (!visited[*i])
DFSUtil(*i, visited);
}
// Function that returns reverse (or transpose) of this graph
// This function is needed in isSC()
Graph Graph::getTranspose()
{
Graph g(V);
for (int v = 0; v < V; v++)
{
// Recur for all the vertices adjacent to this vertex
list<int>::iterator i;
for(i = adj[v].begin(); i != adj[v].end(); ++i)
{
g.adj[*i].push_back(v);
(g.in[v])++;
}
}
return g;
}
// This function returns true if all non-zero degree vertices of
// graph are strongly connected. Please refer
// https://www.geeksforgeeks.org/connectivity-in-a-directed-graph/
bool Graph::isSC()
{
// Mark all the vertices as not visited (For first DFS)
bool visited[V];
for (int i = 0; i < V; i++)
visited[i] = false;
// Find the first vertex with non-zero degree
int n;
for (n = 0; n < V; n++)
282
Chapter 31. Find if the strings can be chained to form a circle
283
Chapter 31. Find if the strings can be chained to form a circle
Python
284
Chapter 31. Find if the strings can be chained to form a circle
# Do DFS traversal starting from first non zero degree vertex.
self.DFSUtil(n, visited)
# If DFS traversal doesn't visit all vertices, then return false.
for i in xrange(self.V):
if len(self.adj[i]) > 0 and visited[i] == False:
return False
# Create a reversed graph
gr = self.getTranspose()
# Mark all the vertices as not visited (For second DFS)
for i in xrange(self.V):
visited[i] = False
# Do DFS for reversed graph starting from first vertex.
# Staring Vertex must be same starting point of first DFS
gr.DFSUtil(n, visited)
# If all vertices are not visited in second DFS, then
# return false
for i in xrange(self.V):
if len(self.adj[i]) > 0 and visited[i] == False:
return False
return True
# This function returns true if the directed graph has an eulerian
# cycle, otherwise returns false
def isEulerianCycle(self):
# Check if all non-zero degree vertices are connected
if self.isSC() == False:
return False
# Check if in degree and out degree of every vertex is same
for i in xrange(self.V):
if len(self.adj[i]) != self.inp[i]:
return False
return True
# A recursive function to do DFS starting from v
def DFSUtil(self, v, visited):
# Mark the current node as visited and print it
visited[v] = True
285
Chapter 31. Find if the strings can be chained to form a circle
286
Chapter 31. Find if the strings can be chained to form a circle
# This code is contributed by BHAVYA JAIN
Output:
Can be chained
Can't be chained
Source
https://www.geeksforgeeks.org/given-array-strings-find-strings-can-chained-form-circle/
287
Chapter 32
Input: contact[] =
{ {"Gaurav", "gaurav@gmail.com", "gaurav@gfgQA.com"},
{ "Lucky", "lucky@gmail.com", "+1234567"},
{ "gaurav123", "+5412312", "gaurav123@skype.com"}.
{ "gaurav1993", "+5412312", "gaurav@gfgQA.com"}
}
Output:
0 2 3
1
contact[2] is same as contact[3] because they both have same
contact number.
contact[0] is same as contact[3] because they both have same
e-mail address.
Therefore, contact[0] and contact[2] are also same.
We strongly recommend you to minimize your browser and try this yourself
first.
288
Chapter 32. Find same contacts in a list of contacts
Input is basically an array of structures. A structure contains three fields such that any
field can represent any detail about a contact.
The idea is to first create a graph of contacts using given array. In the graph, there is an
edge between vertex i to vertex j if they both have either same username or same email or
same phone number. Once the graph is constructed, the task reduces to finding connected
components in an undirected graph. We can find connected components either by doing
DFSor BFSstarting from every unvisited vertex. In below code, DFS is used.
Below is C++ implementation of this idea.
289
Chapter 32. Find same contacts in a list of contacts
mat[j][i] = 1;
break;
}
}
}
// A recuesive function to perform DFS with vertex i as source
void DFSvisit(int i, int *mat[], bool visited[], vector<int>& sol, int n)
{
visited[i] = true;
sol.push_back(i);
for (int j = 0; j < n; j++)
if (mat[i][j] && !visited[j])
DFSvisit(j, mat, visited, sol, n);
}
// Finds similar contacrs in an array of contacts
void findSameContacts(contact arr[], int n)
{
// vector for storing the solution
vector<int> sol;
// Declare 2D adjaceny matrix for mats
int **mat = new int*[n];
for (int i = 0; i < n; i++)
mat[i] = new int[n];
// visited array to keep track of visited nodes
bool visited[n];
memset(visited, 0, sizeof(visited));
// Fill adjacency matrix
buildGraph(arr, n, mat);
// Since, we made a graph with contacts as nodes with fields as links.
// two nodes are linked if they represent the same person.
// so, total number of connected components and nodes in each component
// will be our answer.
for (int i = 0; i < n; i++)
{
if (!visited[i])
{
DFSvisit(i, mat, visited, sol, n);
// Add delimeter to separate nodes of one component from other.
sol.push_back(-1);
290
Chapter 32. Find same contacts in a list of contacts
}
}
// Print the solution
for (int i = 0; i < sol.size(); i++)
if (sol[i] == -1) cout << endl;
else cout << sol[i] << " ";
}
// Drive program
int main()
{
contact arr[] = {{"Gaurav", "gaurav@gmail.com", "gaurav@gfgQA.com"},
{"Lucky", "lucky@gmail.com", "+1234567"},
{"gaurav123", "+5412312", "gaurav123@skype.com"},
{"gaurav1993", "+5412312", "gaurav@gfgQA.com"},
{"raja", "+2231210", "raja@gfg.com"},
{"bahubali", "+878312", "raja"}
};
int n = sizeof arr / sizeof arr[0];
findSameContacts(arr, n);
return 0;
}
Output:
0 3 2
1
4 5
Source
https://www.geeksforgeeks.org/find-same-contacts-in-a-list-of-contacts/
291
Chapter 33
Input:
cost[N][N] = { {0, 15, 80, 90},
{INF, 0, 40, 50},
{INF, INF, 0, 70},
{INF, INF, INF, 0}
};
There are 4 stations and cost[i][j] indicates cost to reach j
from i. The entries where j < i are meaningless.
Output:
The minimum cost is 65
The minimum cost can be obtained by first going to station 1
from 0. Then from station 1 to station 3.
We strongly recommend to minimize your browser and try this yourself first.
The minimum cost to reach N-1 from 0 can be recursively written as following:
292
Chapter 33. Find the minimum cost to reach destination using a train
293
Chapter 33. Find the minimum cost to reach destination using a train
{
return minCostRec(cost, 0, N-1);
}
// Driver program to test above function
int main()
{
int cost[N][N] = { {0, 15, 80, 90},
{INF, 0, 40, 50},
{INF, INF, 0, 70},
{INF, INF, INF, 0}
};
cout << "The Minimum cost to reach station "
<< N << " is " << minCost(cost);
return 0;
}
Java
294
Chapter 33. Find the minimum cost to reach destination using a train
// This function returns the smallest possible cost to
// reach station N-1 from station 0. This function mainly
// uses minCostRec().
static int minCost(int cost[][])
{
return minCostRec(cost, 0, N-1);
}
public static void main(String args[])
{
int cost[][] = { {0, 15, 80, 90},
{INF, 0, 40, 50},
{INF, INF, 0, 70},
{INF, INF, INF, 0}
};
System.out.println("The Minimum cost to reach station "+ N+
" is "+minCost(cost));
}
}/* This code is contributed by Rajat Mishra */
Python
295
Chapter 33. Find the minimum cost to reach destination using a train
]
print "The Minimum cost to reach station %d is %d" % \
(N, minCost(cost))
# This code is contributed by Divyanshu Mehta
C#
296
Chapter 33. Find the minimum cost to reach destination using a train
Output:
Time complexity of the above implementation is exponential as it tries every possible path
from 0 to N-1. The above solution solves same subrpoblems multiple times (it can be seen
by drawing recursion tree for minCostPathRec(0, 5).
Since this problem has both properties of dynamic programming problems ((see thisand
this). Like other typical Dynamic Programming(DP) problems, re-computations of same
subproblems can be avoided by storing the solutions to subproblems and solving problems
in bottom up manner.
One dynamic programming solution is to create a 2D table and fill the table using above
given recursive formula. The extra space required in this solution would be O(N2 ) and time
complexity would be O(N3 )
We can solve this problem using O(N) extra space and O(N2 ) time. The idea is based on
the fact that given input matrix is a Directed Acyclic Graph (DAG). The shortest path in
DAG can be calculated using the approach discussed in below post.
Shortest Path in Directed Acyclic Graph
We need to do less work here compared to above mentioned post as we know topological
sorting of the graph. The topological sorting of vertices here is 0, 1, ..., N-1. Following is
the idea once topological sorting is known.
The idea in below code is to first calculate min cost for station 1, then for station 2, and so
on. These costs are stored in an array dist[0...N-1].
297
Chapter 33. Find the minimum cost to reach destination using a train
298
Chapter 33. Find the minimum cost to reach destination using a train
{
int cost[N][N] = { {0, 15, 80, 90},
{INF, 0, 40, 50},
{INF, INF, 0, 70},
{INF, INF, INF, 0}
};
cout << "The Minimum cost to reach station "
<< N << " is " << minCost(cost);
return 0;
}
Java
299
Chapter 33. Find the minimum cost to reach destination using a train
Python3
300
Chapter 33. Find the minimum cost to reach destination using a train
C#
301
Chapter 33. Find the minimum cost to reach destination using a train
return dist[N-1];
}
public static void Main()
{
int [,]cost = { {0, 15, 80, 90},
{INF, 0, 40, 50},
{INF, INF, 0, 70},
{INF, INF, INF, 0} };
Console.WriteLine("The Minimum cost to"
+ " reach station "+ N
+ " is "+minCost(cost));
}
}
// This code is contributed by Sam007.
Output:
This article is contributed by Udit Gupta. Please write comments if you find anything
incorrect, or you want to share more information about the topic discussed above.
Improved By : Sam007
Source
https://www.geeksforgeeks.org/find-the-minimum-cost-to-reach-a-destination-where-every-station-is-connected-in-
302
Chapter 34
The idea is to create a graph of characters and then find topological sorting of the created
graph. Following are the detailed steps.
1) Create a graph g with number of vertices equal to the size of alphabet in the given alien
language. For example, if the alphabet size is 5, then there can be 5 characters in words.
Initially there are no edges in graph.
2) Do following for every pair of adjacent words in given sorted array.
…..a) Let the current pair of words be word1 and word2. One by one compare characters of
both words and find the first mismatching characters.
…..b) Create an edge in g from mismatching character of word1 to that of word2.
3) Print topological sorting of the above created graph.
303
Chapter 34. Given a sorted dictionary of an alien language, find order of characters
304
Chapter 34. Given a sorted dictionary of an alien language, find order of characters
list<int>::iterator i;
for (i = adj[v].begin(); i != adj[v].end(); ++i)
if (!visited[*i])
topologicalSortUtil(*i, visited, Stack);
// Push current vertex to stack which stores result
Stack.push(v);
}
// The function to do Topological Sort. It uses recursive topologicalSortUtil()
void Graph::topologicalSort()
{
stack<int> Stack;
// Mark all the vertices as not visited
bool *visited = new bool[V];
for (int i = 0; i < V; i++)
visited[i] = false;
// Call the recursive helper function to store Topological Sort
// starting from all vertices one by one
for (int i = 0; i < V; i++)
if (visited[i] == false)
topologicalSortUtil(i, visited, Stack);
// Print contents of stack
while (Stack.empty() == false)
{
cout << (char) ('a' + Stack.top()) << " ";
Stack.pop();
}
}
int min(int x, int y)
{
return (x < y)? x : y;
}
// This function fidns and prints order of characer from a sorted
// array of words. n is size of words[]. alpha is set of possible
// alphabets.
// For simplicity, this function is written in a way that only
// first 'alpha' characters can be there in words array. For
// example if alpha is 7, then words[] should have only 'a', 'b',
// 'c' 'd', 'e', 'f', 'g'
void printOrder(string words[], int n, int alpha)
{
// Create a graph with 'aplha' edges
305
Chapter 34. Given a sorted dictionary of an alien language, find order of characters
Graph g(alpha);
// Process all adjacent pairs of words and create a graph
for (int i = 0; i < n-1; i++)
{
// Take the current two words and find the first mismatching
// character
string word1 = words[i], word2 = words[i+1];
for (int j = 0; j < min(word1.length(), word2.length()); j++)
{
// If we find a mismatching character, then add an edge
// from character of word1 to that of word2
if (word1[j] != word2[j])
{
g.addEdge(word1[j]-'a', word2[j]-'a');
break;
}
}
}
// Print topological sort of the above created graph
g.topologicalSort();
}
// Driver program to test above functions
int main()
{
string words[] = {"caa", "aaa", "aab"};
printOrder(words, 3, 3);
return 0;
}
Java
306
Chapter 34. Given a sorted dictionary of an alien language, find order of characters
307
Chapter 34. Given a sorted dictionary of an alien language, find order of characters
// Call the recursive helper function to store Topological
// Sort starting from all vertices one by one
for (int i = 0; i < getNoOfVertices(); i++)
{
if (!visited[i])
{
topologicalSortUtil(i, visited, stack);
}
}
// Print contents of stack
while (!stack.isEmpty())
{
System.out.print((char)('a' + stack.pop()) + " ");
}
}
}
public class OrderOfCharacters
{
// This function fidns and prints order
// of characer from a sorted array of words.
// alpha is number of possible alphabets
// starting from 'a'. For simplicity, this
// function is written in a way that only
// first 'alpha' characters can be there
// in words array. For example if alpha
// is 7, then words[] should contain words
// having only 'a', 'b','c' 'd', 'e', 'f', 'g'
private static void printOrder(String[] words, int alpha)
{
// Create a graph with 'aplha' edges
Graph graph = new Graph(alpha);
for (int i = 0; i < words.length - 1; i++)
{
// Take the current two words and find the first mismatching
// character
String word1 = words[i];
String word2 = words[i+1];
for (int j = 0; j < Math.min(word1.length(), word2.length()); j++)
{
// If we find a mismatching character, then add an edge
// from character of word1 to that of word2
if (word1.charAt(j) != word2.charAt(j))
{
graph.addEdge(word1.charAt(j) - 'a', word2.charAt(j)- 'a');
308
Chapter 34. Given a sorted dictionary of an alien language, find order of characters
break;
}
}
}
// Print topological sort of the above created graph
graph.topologicalSort();
}
// Driver program to test above functions
public static void main(String[] args)
{
String[] words = {"caa", "aaa", "aab"};
printOrder(words, 3);
}
}
//Contributed by Harikrishnan Rajan
Output:
c a b
Time Complexity: The first step to create a graph takes O(n + alhpa) time where n is
number of given words and alpha is number of characters in given alphabet. The second
step is also topological sorting. Note that there would be alpha vertices and at-most (n-1)
edges in the graph. The time complexity of topological sorting is O(V+E) which is O(n +
aplha) here. So overall time complexity is O(n + aplha) + O(n + aplha) which is O(n +
aplha).
Exercise:
The above code doesn’t work when the input is not valid. For example {“aba”, “bba”,
“aaa”} is not valid, because from first two words, we can deduce ‘a’ should appear before ‘b’,
but from last two words, we can deduce ‘b’ should appear before ‘a’ which is not possible.
Extend the above program to handle invalid inputs and generate the output as “Not valid”.
This article is contributed by Piyush Gupta. Please write comments if you find anything
incorrect, or you want to share more information about the topic discussed above.
Source
https://www.geeksforgeeks.org/given-sorted-dictionary-find-precedence-characters/
309
Chapter 35
The idea is to use BFS. We start from the given start word, traverse all words that adjacent
(differ by one character) to it and keep doing so until we find the target word or we have
traversed all words.
Below is C++ implementation of above idea.
C
310
Chapter 35. Length of shortest chain to reach a target word
311
Chapter 35. Length of shortest chain to reach a target word
item.word = temp;
item.len = curr.len + 1;
Q.push(item);
// Remove from dictionary so that this word is not
// processed again. This is like marking visited
D.erase(temp);
// If we reached target
if (temp == target)
return item.len;
}
}
}
return 0;
}
// Driver program
int main()
{
// make dictionary
set<string> D;
D.insert("poon");
D.insert("plee");
D.insert("same");
D.insert("poie");
D.insert("plie");
D.insert("poin");
D.insert("plea");
string start = "toon";
string target = "plea";
cout << "Length of shortest chain is: "
<< shortestChainLen(start, target, D);
return 0;
}
Python
312
Chapter 35. Length of shortest chain to reach a target word
313
Chapter 35. Length of shortest chain to reach a target word
Output:
Time Complexity of the above code is O(n²m) where n is the number of entries originally
in the dictionary and m is the size of the string
Thanks to Gaurav Ahirwar and Rajnish Kumar Jha for above solution.
Source
https://www.geeksforgeeks.org/word-ladder-length-of-shortest-chain-to-reach-a-target-word/
314
Chapter 36
0: Empty cell
So we have to determine what is the minimum time required so that all the oranges become
rotten. A rotten orange at index [i,j] can rot other fresh orange at indexes [i-1,j], [i+1,j],
[i,j-1], [i,j+1] (up, down, left and right). If it is impossible to rot every orange then simply
return -1.
Examples:
315
Chapter 36. Minimum time required to rot all oranges
{1, 0, 0, 2, 1}};
Output:
All oranges cannot be rotten.
1) Create an empty Q.
2) Find all rotten oranges and enqueue them to Q. Also enqueue
a delimiter to indicate beginning of next time frame.
3) While Q is not empty do following
3.a) While delimiter in Q is not reached
(i) Dequeue an orange from queue, rot all adjacent oranges.
While rotting the adjacents, make sure that time frame
is incremented only once. And time frame is not icnremented
if there are no adjacent oranges.
3.b) Dequeue the old delimiter and enqueue a new delimiter. The
oranges rotten in previous time frame lie between the two
delimiters.
316
Chapter 36. Minimum time required to rot all oranges
// Function to check whether there is still a fresh
// orange remaining
bool checkall(int arr[][C])
{
for (int i=0; i<R; i++)
for (int j=0; j<C; j++)
if (arr[i][j] == 1)
return true;
return false;
}
// This function finds if it is possible to rot all oranges or not.
// If possible, then it returns minimum time required to rot all,
// otherwise returns -1
int rotOranges(int arr[][C])
{
// Create a queue of cells
queue<ele> Q;
ele temp;
int ans = 0;
// Store all the cells having rotten orange in first time frame
for (int i=0; i<R; i++)
{
for (int j=0; j<C; j++)
{
if (arr[i][j] == 2)
{
temp.x = i;
temp.y = j;
Q.push(temp);
}
}
}
// Separate these rotten oranges from the oranges which will rotten
// due the oranges in first time frame using delimiter which is (-1, -1)
temp.x = -1;
temp.y = -1;
Q.push(temp);
// Process the grid while there are rotten oranges in the Queue
while (!Q.empty())
{
// This flag is used to determine whether even a single fresh
// orange gets rotten due to rotten oranges in current time
// frame so we can increase the count of the required time.
317
Chapter 36. Minimum time required to rot all oranges
318
Chapter 36. Minimum time required to rot all oranges
}
Q.pop();
}
// Pop the delimiter
Q.pop();
// If oranges were rotten in current frame than separate the
// rotten oranges using delimiter for the next frame for processing.
if (!Q.empty()) {
temp.x = -1;
temp.y = -1;
Q.push(temp);
}
// If Queue was empty than no rotten oranges left to process so exit
}
// Return -1 if all arranges could not rot, otherwise -1.
return (checkall(arr))? -1: ans;
}
// Drive program
int main()
{
int arr[][C] = { {2, 1, 0, 2, 1},
{1, 0, 1, 2, 1},
{1, 0, 0, 2, 1}};
int ans = rotOranges(arr);
if (ans == -1)
cout << "All oranges cannot rotn";
else
cout << "Time required for all oranges to rot => " << ans << endl;
return 0;
}
Java
319
Chapter 36. Minimum time required to rot all oranges
320
Chapter 36. Minimum time required to rot all oranges
// Store all the cells having rotten orange in first time frame
for (int i=0; i < R; i++)
for (int j=0; j < C; j++)
if (arr[i][j] == 2)
Q.add(new Ele(i,j));
// Separate these rotten oranges from the oranges which will rotten
// due the oranges in first time frame using delimiter which is (-1, -1)
Q.add(new Ele(-1,-1));
// Process the grid while there are rotten oranges in the Queue
while(!Q.isEmpty())
{
// This flag is used to determine whether even a single fresh
// orange gets rotten due to rotten oranges in current time
// frame so we can increase the count of the required time.
boolean flag = false;
// Process all the rotten oranges in current time frame.
while(!isDelim(Q.peek()))
{
temp = Q.peek();
// Check right adjacent cell that if it can be rotten
if(isValid(temp.x+1, temp.y+1) && arr[temp.x+1][temp.y] == 1)
{
if(!flag)
{
// if this is the first orange to get rotten, increase
// count and set the flag.
ans++;
flag = true;
}
// Make the orange rotten
arr[temp.x+1][temp.y] = 2;
// push the adjacent orange to Queue
temp.x++;
Q.add(new Ele(temp.x,temp.y));
// Move back to current cell
temp.x--;
}
// Check left adjacent cell that if it can be rotten
if (isValid(temp.x-1, temp.y) && arr[temp.x-1][temp.y] == 1)
{
if (!flag)
321
Chapter 36. Minimum time required to rot all oranges
{
ans++;
flag = true;
}
arr[temp.x-1][temp.y] = 2;
temp.x--;
Q.add(new Ele(temp.x,temp.y)); // push this cell to Queue
temp.x++;
}
// Check top adjacent cell that if it can be rotten
if (isValid(temp.x, temp.y+1) && arr[temp.x][temp.y+1] == 1) {
if(!flag)
{
ans++;
flag = true;
}
arr[temp.x][temp.y+1] = 2;
temp.y++;
Q.add(new Ele(temp.x,temp.y)); // Push this cell to Queue
temp.y--;
}
// Check bottom adjacent cell if it can be rotten
if (isValid(temp.x, temp.y-1) && arr[temp.x][temp.y-1] == 1)
{
if (!flag)
{
ans++;
flag = true;
}
arr[temp.x][temp.y-1] = 2;
temp.y--;
Q.add(new Ele(temp.x,temp.y)); // push this cell to Queue
}
Q.remove();
}
// Pop the delimiter
Q.remove();
// If oranges were rotten in current frame than separate the
// rotten oranges using delimiter for the next frame for processing.
if (!Q.isEmpty())
{
Q.add(new Ele(-1,-1));
}
322
Chapter 36. Minimum time required to rot all oranges
// If Queue was empty than no rotten oranges left to process so exit
}
// Return -1 if all arranges could not rot, otherwise -1.s
return (checkAll(arr))? -1: ans;
}
// Drive program
public static void main(String[] args)
{
int arr[][] = { {2, 1, 0, 2, 1},
{1, 0, 1, 2, 1},
{1, 0, 0, 2, 1}};
int ans = rotOranges(arr);
if(ans == -1)
System.out.println("All oranges cannot rot");
else
System.out.println("Time required for all oranges to rot = " + ans);
}
}
//This code is contributed by Sumit Ghosh
Output:
Source
https://www.geeksforgeeks.org/minimum-time-required-so-that-all-oranges-become-rotten/
323
Chapter 37
Example 1:
Input: Number of Days to Finish book = 2
Number of pages in chapters = {10, 5, 5}
Output: Day 1: Chapter 1
Day 2: Chapters 2 and 3
Example 2:
Input: Number of Days to Finish book = 3
Number of pages in chapters = {8, 5, 6, 12}
Output: Day 1: Chapter 1
Day 2: Chapters 2 and 3
Day 2: Chapter 4
The target is to minimize the sum of differences between the pages read on each day and
average number of pages. If the average number of pages is a non-integer, then it should be
rounded to closest integer.
In above example 2, average number of pages is (8 + 5 + 6 + 12)/3 = 31/3 which is rounded
to 10. So the difference between average and number of pages on each day for the output
shown above is “abs(8-10) + abs(5+6-10) + abs(12-10)” which is 5. The value 5 is the
optimal value of sum of differences.
Consider the example 2 above where a book has 4 chapters with pages 8, 5, 6 and 12. User
wishes to finish it in 3 days. The graphical representation of the above scenario is,
324
Chapter 37. Optimal read list for given number of days
In the above graph vertex represents the chapter and an edge e(u, v) represents number of
pages to be read to reach ‘v ‘ from ‘u ‘. Sink node is added to symbolize the end of book.
First, calculate the average number of pages to read in a day (here 31/3 roughly 10). New
edge weight e ‘(u, v) would be the mean difference avg – e(u, v). Modified graph for the
above problem would be,
325
Chapter 37. Optimal read list for given number of days
326
Chapter 37. Optimal read list for given number of days
updateAssignment(path, path_len);
min = sum;
}
}
// DFS - Depth First Search for sink
for (int v = u+1; v <= CHAPTERS; v++)
{
sum += DAG[u][v];
assignChapters(v, path, path_len, sum, k-1);
sum -= DAG[u][v];
}
}
// This function finds and prints optimal read list. It first creates a
// graph, then calls assignChapters().
void minAssignment(int pages[])
{
// 1) ............CONSTRUCT GRAPH.................
// Partial sum array construction S[i] = total pages
// till ith chapter
int avg_pages = 0, sum = 0, S[CHAPTERS+1], path[DAYS+1];
S[0] = 0;
for (int i = 0; i < CHAPTERS; i++)
{
sum += pages[i];
S[i+1] = sum;
}
// Average pages to be read in a day
avg_pages = round(sum/DAYS);
/* DAG construction vertices being chapter name &
* Edge weight being |avg_pages - pages in a chapter|
* Adjacency matrix representation */
for (int i = 0; i <= CHAPTERS; i++)
{
for (int j = 0; j <= CHAPTERS; j++)
{
if (j <= i)
DAG[i][j] = NOLINK;
else
{
sum = abs(avg_pages - (S[j] - S[i]));
DAG[i][j] = sum;
}
}
327
Chapter 37. Optimal read list for given number of days
}
// 2) ............FIND OPTIMAL PATH................
assignChapters(0, path, 0, 0, DAYS);
// 3) ..PRINT OPTIMAL READ LIST USING OPTIMAL PATH....
cout << "Optimal Chapter Assignment :" << endl;
int ch;
for (int i = 0; i < DAYS; i++)
{
ch = optimal_path[i];
cout << "Day" << i+1 << ": " << ch << " ";
ch++;
while ( (i < DAYS-1 && ch < optimal_path[i+1]) ||
(i == DAYS-1 && ch <= CHAPTERS))
{
cout << ch << " ";
ch++;
}
cout << endl;
}
}
// This funtion updates optimal_path[]
void updateAssignment(int* path, int path_len)
{
for (int i = 0; i < path_len; i++)
optimal_path[i] = path[i] + 1;
}
// Driver program to test the schedule
int main(void)
{
int pages[CHAPTERS] = {7, 5, 6, 12};
// Get read list for given days
minAssignment(pages);
return 0;
}
Output:
328
Chapter 37. Optimal read list for given number of days
This article is contributed by Balaji S. Please write comments if you find anything incorrect,
or you want to share more information about the topic discussed above.
Source
https://www.geeksforgeeks.org/optimal-read-list-given-number-days/
329
Chapter 38
The idea is to do Depth First Traversal of given directed graph. Start the traversal from
source. Keep storing the visited vertices in an array say ‘path[]’. If we reach the destination
vertex, print contents of path[]. The important thing is to mark current vertices in path[]
as visited also, so that the traversal doesn’t go in a cycle.
Following is implementation of above idea.
C/C++
330
Chapter 38. Print all paths from a given source to a destination
#include<iostream>
#include <list>
using namespace std;
// A directed graph using adjacency list representation
class Graph
{
int V; // No. of vertices in graph
list<int> *adj; // Pointer to an array containing adjacency lists
// A recursive function used by printAllPaths()
void printAllPathsUtil(int , int , bool [], int [], int &);
public:
Graph(int V); // Constructor
void addEdge(int u, int v);
void printAllPaths(int s, int d);
};
Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V];
}
void Graph::addEdge(int u, int v)
{
adj[u].push_back(v); // Add v to u’s list.
}
// Prints all paths from 's' to 'd'
void Graph::printAllPaths(int s, int d)
{
// Mark all the vertices as not visited
bool *visited = new bool[V];
// Create an array to store paths
int *path = new int[V];
int path_index = 0; // Initialize path[] as empty
// Initialize all vertices as not visited
for (int i = 0; i < V; i++)
visited[i] = false;
// Call the recursive helper function to print all paths
printAllPathsUtil(s, d, visited, path, path_index);
}
331
Chapter 38. Print all paths from a given source to a destination
332
Chapter 38. Print all paths from a given source to a destination
Java
333
Chapter 38. Print all paths from a given source to a destination
334
Chapter 38. Print all paths from a given source to a destination
// remove current node
// in path[]
localPathList.remove(i);
}
}
// Mark the current node
isVisited[u] = false;
}
// Driver program
public static void main(String[] args)
{
// Create a sample graph
Graph g = new Graph(4);
g.addEdge(0,1);
g.addEdge(0,2);
g.addEdge(0,3);
g.addEdge(2,0);
g.addEdge(2,1);
g.addEdge(1,3);
// arbitrary source
int s = 2;
// arbitrary destination
int d = 3;
System.out.println("Following are all different paths from "+s+" to "+d);
g.printAllPaths(s, d);
}
}
// This code is contributed by Himanshu Shekhar.
Python
335
Chapter 38. Print all paths from a given source to a destination
#No. of vertices
self.V= vertices
# default dictionary to store graph
self.graph = defaultdict(list)
# function to add an edge to graph
def addEdge(self,u,v):
self.graph[u].append(v)
'''A recursive function to print all paths from 'u' to 'd'.
visited[] keeps track of vertices in current path.
path[] stores actual vertices and path_index is current
index in path[]'''
def printAllPathsUtil(self, u, d, visited, path):
# Mark the current node as visited and store in path
visited[u]= True
path.append(u)
# If current vertex is same as destination, then print
# current path[]
if u ==d:
print path
else:
# If current vertex is not destination
#Recur for all the vertices adjacent to this vertex
for i in self.graph[u]:
if visited[i]==False:
self.printAllPathsUtil(i, d, visited, path)
# Remove current vertex from path[] and mark it as unvisited
path.pop()
visited[u]= False
# Prints all paths from 's' to 'd'
def printAllPaths(self,s, d):
# Mark all the vertices as not visited
visited =[False]*(self.V)
# Create an array to store paths
path = []
# Call the recursive helper function to print all paths
self.printAllPathsUtil(s, d,visited, path)
336
Chapter 38. Print all paths from a given source to a destination
# Create a graph given in the above diagram
g = Graph(4)
g.addEdge(0, 1)
g.addEdge(0, 2)
g.addEdge(0, 3)
g.addEdge(2, 0)
g.addEdge(2, 1)
g.addEdge(1, 3)
s = 2 ; d = 3
print ("Following are all different paths from %d to %d :" %(s, d))
g.printAllPaths(s, d)
#This code is contributed by Neelam Yadav
Output:
This article is contributed by Shivam Gupta. Please write comments if you find anything
incorrect, or you want to share more information about the topic discussed above
Source
https://www.geeksforgeeks.org/find-paths-given-source-destination/
337
Chapter 39
Print all Jumping Numbers smaller than or equal to a given value - GeeksforGeeks
A number is called as a Jumping Number if all adjacent digits in it differ by 1. The difference
between ‘9’ and ‘0’ is not considered as 1.
All single digit numbers are considered as Jumping Numbers. For example 7, 8987 and
4343456 are Jumping numbers but 796 and 89098 are not.
Given a positive number x, print all Jumping Numbers smaller than or equal to x. The
numbers can be printed in any order.
Example:
Input: x = 20
Output: 0 1 2 3 4 5 6 7 8 9 10 12
Input: x = 105
Output: 0 1 2 3 4 5 6 7 8 9 10 12
21 23 32 34 43 45 54 56 65
67 76 78 87 89 98 101
One Simple Solution is to traverse all numbers from 0 to x. For every traversed number,
check if it is a Jumping number. If yes, then print it. Otherwise ignore it. Time Complexity
of this solution is O(x).
338
Chapter 39. Print all Jumping Numbers smaller than or equal to a given value
An Efficient Solution can solve this problem in O(k) time where k is number of Jumping
Numbers smaller than or equal to x. The idea is use BFS or DFS.
Assume that we have a graph where the starting node is 0 and we need to traverse it from
the start node to all the reachable nodes.
With the restrictions given in the graph about the jumping numbers, what do you think
should be the restrictions defining the next transitions in the graph.
Start node = 0
From 0, we can move to 1 2 3 4 5 6 7 8 9
[these are not in our range so we don't add it]
339
Chapter 39. Print all Jumping Numbers smaller than or equal to a given value
if (num <= x)
{
cout << num << " ";
int last_dig = num % 10;
// If last digit is 0, append next digit only
if (last_dig == 0)
q.push((num*10) + (last_dig+1));
// If last digit is 9, append previous digit only
else if (last_dig == 9)
q.push( (num*10) + (last_dig-1) );
// If last digit is neighter 0 nor 9, append both
// previous and next digits
else
{
q.push((num*10) + (last_dig-1));
q.push((num*10) + (last_dig+1));
}
}
}
}
// Prints all jumping numbers smaller than or equal to
// a positive number x
void printJumping(int x)
{
cout << 0 << " ";
for (int i=1; i<=9 && i<=x; i++)
bfs(x, i);
}
// Driver program
int main()
{
int x = 40;
printJumping(x);
return 0;
}
Python 3
340
Chapter 39. Print all Jumping Numbers smaller than or equal to a given value
self.lst = []
def is_empty(self):
return self.lst == []
def enqueue(self, elem):
self.lst.append(elem)
def dequeue(self):
return self.lst.pop(0)
# Prints all jumping numbers smaller than or equal to
# x starting with 'num'. It mainly does BFS starting
# from 'num'.
def bfs(x,num):
# Create a queue and enqueue i to it
q = Queue()
q.enqueue(num)
# Do BFS starting from 1
while (not q.is_empty()):
num = q.dequeue()
if num<=x:
print(str(num),end=' ')
last_dig = num % 10
# If last digit is 0, append next digit only
if last_dig == 0:
q.enqueue((num * 10) + (last_dig + 1))
# If last digit is 9, append previous digit
# only
elif last_dig == 9:
q.enqueue((num * 10) + (last_dig - 1))
# If last digit is neighter 0 nor 9, append
# both previous digit and next digit
else:
q.enqueue((num * 10) + (last_dig - 1))
q.enqueue((num * 10) + (last_dig + 1))
# Prints all jumping numbers smaller than or equal to
# a positive number x
def printJumping(x):
print (str(0), end=' ')
for i in range(1,10):
341
Chapter 39. Print all Jumping Numbers smaller than or equal to a given value
bfs(x, i)
# Driver Program ( Change value of x as desired )
x = 40
printJumping(x)
# This code is contributed by Saket Modi
Output:
0 1 10 12 2 21 23 3 32 34 4 5 6 7 8 9
2. Extend your solution to print all numbers in sorted order instead of any order.
3. Further extend the solution to print all numbers in a given range.
Improved By : fruit_jam
Source
https://www.geeksforgeeks.org/print-all-jumping-numbers-smaller-than-or-equal-to-a-given-value/
342
Chapter 40
343
Chapter 40. Stable Marriage Problem
w = m's highest ranked such woman to whom he has not yet proposed
if w is free
(m, w) become engaged
else some pair (m', w) already exists
if w prefers m to m'
(m, w) become engaged
m' becomes free
else
(m', w) remain engaged
}
Input & Output: Input is a 2D matrix of size (2*N)*N where N is number of women or
men. Rows from 0 to N-1 represent preference lists of men and rows from N to 2*N – 1
represent preference lists of women. So men are numbered from 0 to N-1 and women are
numbered from N to 2*N – 1. The output is list of married pairs.
Following is C++ implementation of the above algorithm.
344
Chapter 40. Stable Marriage Problem
{
// Stores partner of women. This is our output array that
// stores paing information. The value of wPartner[i]
// indicates the partner assigned to woman N+i. Note that
// the woman numbers between N and 2*N-1. The value -1
// indicates that (N+i)'th woman is free
int wPartner[N];
// An array to store availability of men. If mFree[i] is
// false, then man 'i' is free, otherwise engaged.
bool mFree[N];
// Initialize all men and women as free
memset(wPartner, -1, sizeof(wPartner));
memset(mFree, false, sizeof(mFree));
int freeCount = N;
// While there are free men
while (freeCount > 0)
{
// Pick the first free man (we could pick any)
int m;
for (m = 0; m < N; m++)
if (mFree[m] == false)
break;
// One by one go to all women according to m's preferences.
// Here m is the picked free man
for (int i = 0; i < N && mFree[m] == false; i++)
{
int w = prefer[m][i];
// The woman of preference is free, w and m become
// partners (Note that the partnership maybe changed
// later). So we can say they are engaged not married
if (wPartner[w-N] == -1)
{
wPartner[w-N] = m;
mFree[m] = true;
freeCount--;
}
else // If w is not free
{
// Find current engagement of w
int m1 = wPartner[w-N];
// If w prefers m over her current engagement m1,
345
Chapter 40. Stable Marriage Problem
Output:
Woman Man
4 2
5 1
6 3
7 0
References:
http://www.csee.wvu.edu/~ksmani/courses/fa01/random/lecnotes/lecture5.pdf
http://www.youtube.com/watch?v=5RSMLgy06Ew#t=11m4s
Improved By : ParulShandilya
346
Chapter 40. Stable Marriage Problem
Source
https://www.geeksforgeeks.org/stable-marriage-problem/
347
Chapter 41
The Steiner Tree Problem is to find the minimum cost Steiner Tree. See below
for an example.
348
Chapter 41. Steiner Tree Problem
349
Chapter 41. Steiner Tree Problem
The above algorithm is (2-2/n) approximate, i.e., it guarantees that solution produced by
this algorithm is not more than this ration of optimized solution for a given graph with n
vertices. There are better algorithms also that provide better ratio. Refer below reference
for more details.
References:
www.cs.uu.nl/docs/vakken/an/teoud/an-steiner.ppt
This article is contributed by Shivam Gupta. Please write comments if you find anything
incorrect, or you want to share more information about the topic discussed above
Source
https://www.geeksforgeeks.org/steiner-tree/
350
Chapter 42
It is easy for undirected graph, we can just do a BFS and DFS starting from any
vertex. If BFS or DFS visits all vertices, then the given undirected graph is connected. This
approach won’t work for a directed graph. For example, consider the following graph which
is not strongly connected. If we start DFS (or BFS) from vertex 0, we can reach all vertices,
but if we start from any other vertex, we cannot reach all vertices.
351
Chapter 42. Connectivity in a directed graph
We can also do DFSV times starting from every vertex. If any DFS, doesn’t visit all
vertices, then graph is not strongly connected. This algorithm takes O(V*(V+E)) time
which can be same as transitive closure for a dense graph.
A better idea can be Strongly Connected Components (SCC) algorithm. We can
find all SCCs in O(V+E) time. If number of SCCs is one, then graph is strongly connected.
The algorithm for SCC does extra work as it finds all SCCs.
Following is Kosaraju’s DFS based simple algorithm that does two DFS traversals
of graph:
1) Initialize all vertices as not visited.
2) Do a DFS traversal of graph starting from any arbitrary vertex v. If DFS traversal
doesn’t visit all vertices, then return false.
3) Reverse all arcs (or find transpose or reverse of graph)
4) Mark all vertices as not-visited in reversed graph.
5) Do a DFS traversal of reversed graph starting from same vertex v (Same as step 2). If
DFS traversal doesn’t visit all vertices, then return false. Otherwise return true.
The idea is, if every node can be reached from a vertex v, and every node can reach v, then
the graph is strongly connected. In step 2, we check if all vertices are reachable from v. In
step 4, we check if all vertices can reach v (In reversed graph, if all vertices are reachable
from v, then all vertices can reach v in original graph).
Following is the implementation of above algorithm.
C++
352
Chapter 42. Connectivity in a directed graph
// The main function that returns true if the graph is strongly
// connected, otherwise false
bool isSC();
// Function that returns reverse (or transpose) of this graph
Graph getTranspose();
};
// A recursive function to print DFS starting from v
void Graph::DFSUtil(int v, bool visited[])
{
// Mark the current node as visited and print it
visited[v] = true;
// Recur for all the vertices adjacent to this vertex
list<int>::iterator i;
for (i = adj[v].begin(); i != adj[v].end(); ++i)
if (!visited[*i])
DFSUtil(*i, visited);
}
// Function that returns reverse (or transpose) of this graph
Graph Graph::getTranspose()
{
Graph g(V);
for (int v = 0; v < V; v++)
{
// Recur for all the vertices adjacent to this vertex
list<int>::iterator i;
for(i = adj[v].begin(); i != adj[v].end(); ++i)
{
g.adj[*i].push_back(v);
}
}
return g;
}
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w); // Add w to v’s list.
}
// The main function that returns true if graph is strongly connected
bool Graph::isSC()
{
// St1p 1: Mark all the vertices as not visited (For first DFS)
bool visited[V];
353
Chapter 42. Connectivity in a directed graph
354
Chapter 42. Connectivity in a directed graph
Java
355
Chapter 42. Connectivity in a directed graph
}
// Function that returns transpose of this graph
Graph getTranspose()
{
Graph g = new Graph(V);
for (int v = 0; v < V; v++)
{
// Recur for all the vertices adjacent to this vertex
Iterator<Integer> i = adj[v].listIterator();
while (i.hasNext())
g.adj[i.next()].add(v);
}
return g;
}
// The main function that returns true if graph is strongly
// connected
Boolean isSC()
{
// Step 1: Mark all the vertices as not visited
// (For first DFS)
Boolean visited[] = new Boolean[V];
for (int i = 0; i < V; i++)
visited[i] = false;
// Step 2: Do DFS traversal starting from first vertex.
DFSUtil(0, visited);
// If DFS traversal doesn't visit all vertices, then
// return false.
for (int i = 0; i < V; i++)
if (visited[i] == false)
return false;
// Step 3: Create a reversed graph
Graph gr = getTranspose();
// Step 4: Mark all the vertices as not visited (For
// second DFS)
for (int i = 0; i < V; i++)
visited[i] = false;
// Step 5: Do DFS for reversed graph starting from
// first vertex. Staring Vertex must be same starting
// point of first DFS
gr.DFSUtil(0, visited);
356
Chapter 42. Connectivity in a directed graph
Python
357
Chapter 42. Connectivity in a directed graph
358
Chapter 42. Connectivity in a directed graph
# Step 4: Mark all the vertices as not visited (For second DFS)
visited =[False]*(self.V)
# Step 5: Do DFS for reversed graph starting from first vertex.
# Staring Vertex must be same starting point of first DFS
gr.DFSUtil(0,visited)
# If all vertices are not visited in second DFS, then
# return false
if any(i == False for i in visited):
return False
return True
# Create a graph given in the above diagram
g1 = Graph(5)
g1.addEdge(0, 1)
g1.addEdge(1, 2)
g1.addEdge(2, 3)
g1.addEdge(3, 0)
g1.addEdge(2, 4)
g1.addEdge(4, 2)
print "Yes" if g1.isSC() else "No"
g2 = Graph(4)
g2.addEdge(0, 1)
g2.addEdge(1, 2)
g2.addEdge(2, 3)
print "Yes" if g2.isSC() else "No"
#This code is contributed by Neelam Yadav
Output:
Yes
No
359
Chapter 42. Connectivity in a directed graph
References:
http://www.ieor.berkeley.edu/~hochbaum/files/ieor266-2012.pdf
Source
https://www.geeksforgeeks.org/connectivity-in-a-directed-graph/
360
Chapter 43
361
Chapter 43. Articulation Points (or Cut Vertices) in a Graph
We do DFS traversal of given graph with additional code to find out Articulation Points
362
Chapter 43. Articulation Points (or Cut Vertices) in a Graph
(APs). In DFS traversal, we maintain a parent[] array where parent[u] stores parent of
vertex u. Among the above mentioned two cases, the first case is simple to detect. For every
vertex, count children. If currently visited vertex u is root (parent[u] is NIL) and has more
than two children, print it.
How to handle second case? The second case is trickier. We maintain an array disc[] to
store discovery time of vertices. For every node u, we need to find out the earliest visited
vertex (the vertex with minimum discovery time) that can be reached from subtree rooted
with u. So we maintain an additional array low[] which is defined as follows.
Following are C++, Java and Python implementation of Tarjan’s algorithm for finding
articulation points.
C++
363
Chapter 43. Articulation Points (or Cut Vertices) in a Graph
}
// A recursive function that find articulation points using DFS traversal
// u --> The vertex to be visited next
// visited[] --> keeps tract of visited vertices
// disc[] --> Stores discovery times of visited vertices
// parent[] --> Stores parent vertices in DFS tree
// ap[] --> Store articulation points
void Graph::APUtil(int u, bool visited[], int disc[],
int low[], int parent[], bool ap[])
{
// A static variable is used for simplicity, we can avoid use of static
// variable by passing a pointer.
static int time = 0;
// Count of children in DFS Tree
int children = 0;
// Mark the current node as visited
visited[u] = true;
// Initialize discovery time and low value
disc[u] = low[u] = ++time;
// Go through all vertices aadjacent to this
list<int>::iterator i;
for (i = adj[u].begin(); i != adj[u].end(); ++i)
{
int v = *i; // v is current adjacent of u
// If v is not visited yet, then make it a child of u
// in DFS tree and recur for it
if (!visited[v])
{
children++;
parent[v] = u;
APUtil(v, visited, disc, low, parent, ap);
// Check if the subtree rooted with v has a connection to
// one of the ancestors of u
low[u] = min(low[u], low[v]);
// u is an articulation point in following cases
// (1) u is root of DFS tree and has two or more chilren.
if (parent[u] == NIL && children > 1)
ap[u] = true;
364
Chapter 43. Articulation Points (or Cut Vertices) in a Graph
// (2) If u is not root and low value of one of its child is more
// than discovery value of u.
if (parent[u] != NIL && low[v] >= disc[u])
ap[u] = true;
}
// Update low value of u for parent function calls.
else if (v != parent[u])
low[u] = min(low[u], disc[v]);
}
}
// The function to do DFS traversal. It uses recursive function APUtil()
void Graph::AP()
{
// Mark all the vertices as not visited
bool *visited = new bool[V];
int *disc = new int[V];
int *low = new int[V];
int *parent = new int[V];
bool *ap = new bool[V]; // To store articulation points
// Initialize parent and visited, and ap(articulation point) arrays
for (int i = 0; i < V; i++)
{
parent[i] = NIL;
visited[i] = false;
ap[i] = false;
}
// Call the recursive helper function to find articulation points
// in DFS tree rooted with vertex 'i'
for (int i = 0; i < V; i++)
if (visited[i] == false)
APUtil(i, visited, disc, low, parent, ap);
// Now ap[] contains articulation points, print them
for (int i = 0; i < V; i++)
if (ap[i] == true)
cout << i << " ";
}
// Driver program to test above function
int main()
{
// Create graphs given in above diagrams
cout << "\nArticulation points in first graph \n";
Graph g1(5);
365
Chapter 43. Articulation Points (or Cut Vertices) in a Graph
g1.addEdge(1, 0);
g1.addEdge(0, 2);
g1.addEdge(2, 1);
g1.addEdge(0, 3);
g1.addEdge(3, 4);
g1.AP();
cout << "\nArticulation points in second graph \n";
Graph g2(4);
g2.addEdge(0, 1);
g2.addEdge(1, 2);
g2.addEdge(2, 3);
g2.AP();
cout << "\nArticulation points in third graph \n";
Graph g3(7);
g3.addEdge(0, 1);
g3.addEdge(1, 2);
g3.addEdge(2, 0);
g3.addEdge(1, 3);
g3.addEdge(1, 4);
g3.addEdge(1, 6);
g3.addEdge(3, 5);
g3.addEdge(4, 5);
g3.AP();
return 0;
}
Java
366
Chapter 43. Articulation Points (or Cut Vertices) in a Graph
Graph(int v)
{
V = v;
adj = new LinkedList[v];
for (int i=0; i<v; ++i)
adj[i] = new LinkedList();
}
//Function to add an edge into the graph
void addEdge(int v, int w)
{
adj[v].add(w); // Add w to v's list.
adj[w].add(v); //Add v to w's list
}
// A recursive function that find articulation points using DFS
// u --> The vertex to be visited next
// visited[] --> keeps tract of visited vertices
// disc[] --> Stores discovery times of visited vertices
// parent[] --> Stores parent vertices in DFS tree
// ap[] --> Store articulation points
void APUtil(int u, boolean visited[], int disc[],
int low[], int parent[], boolean ap[])
{
// Count of children in DFS Tree
int children = 0;
// Mark the current node as visited
visited[u] = true;
// Initialize discovery time and low value
disc[u] = low[u] = ++time;
// Go through all vertices aadjacent to this
Iterator<Integer> i = adj[u].iterator();
while (i.hasNext())
{
int v = i.next(); // v is current adjacent of u
// If v is not visited yet, then make it a child of u
// in DFS tree and recur for it
if (!visited[v])
{
children++;
parent[v] = u;
APUtil(v, visited, disc, low, parent, ap);
367
Chapter 43. Articulation Points (or Cut Vertices) in a Graph
368
Chapter 43. Articulation Points (or Cut Vertices) in a Graph
Python
369
Chapter 43. Articulation Points (or Cut Vertices) in a Graph
370
Chapter 43. Articulation Points (or Cut Vertices) in a Graph
# (1) u is root of DFS tree and has two or more chilren.
if parent[u] == -1 and children > 1:
ap[u] = True
#(2) If u is not root and low value of one of its child is more
# than discovery value of u.
if parent[u] != -1 and low[v] >= disc[u]:
ap[u] = True
# Update low value of u for parent function calls
elif v != parent[u]:
low[u] = min(low[u], disc[v])
#The function to do DFS traversal. It uses recursive APUtil()
def AP(self):
# Mark all the vertices as not visited
# and Initialize parent and visited,
# and ap(articulation point) arrays
visited = [False] * (self.V)
disc = [float("Inf")] * (self.V)
low = [float("Inf")] * (self.V)
parent = [-1] * (self.V)
ap = [False] * (self.V) #To store articulation points
# Call the recursive helper function
# to find articulation points
# in DFS tree rooted with vertex 'i'
for i in range(self.V):
if visited[i] == False:
self.APUtil(i, visited, ap, parent, low, disc)
for index, value in enumerate (ap):
if value == True: print index,
# Create a graph given in the above diagram
g1 = Graph(5)
g1.addEdge(1, 0)
g1.addEdge(0, 2)
g1.addEdge(2, 1)
g1.addEdge(0, 3)
g1.addEdge(3, 4)
print "\nArticulation points in first graph "
g1.AP()
g2 = Graph(4)
371
Chapter 43. Articulation Points (or Cut Vertices) in a Graph
g2.addEdge(0, 1)
g2.addEdge(1, 2)
g2.addEdge(2, 3)
print "\nArticulation points in second graph "
g2.AP()
g3 = Graph (7)
g3.addEdge(0, 1)
g3.addEdge(1, 2)
g3.addEdge(2, 0)
g3.addEdge(1, 3)
g3.addEdge(1, 4)
g3.addEdge(1, 6)
g3.addEdge(3, 5)
g3.addEdge(4, 5)
print "\nArticulation points in third graph "
g3.AP()
#This code is contributed by Neelam Yadav
Output:
Time Complexity: The above function is simple DFS with additional arrays. So time
complexity is same as DFS which is O(V+E) for adjacency list representation of graph.
References:
https://www.cs.washington.edu/education/courses/421/04su/slides/artic.pdf
http://www.slideshare.net/TraianRebedea/algorithm-design-and-complexity-course-8
http://faculty.simpson.edu/lydia.sinapova/www/cmsc250/LN250_Weiss/L25-Connectivity.
htm
Please write comments if you find anything incorrect, or you want to share more information
about the topic discussed above.
Source
https://www.geeksforgeeks.org/articulation-points-or-cut-vertices-in-a-graph/
372
Chapter 44
Biconnected graph
373
Chapter 44. Biconnected graph
374
Chapter 44. Biconnected graph
Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V];
}
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w);
adj[w].push_back(v); // Note: the graph is undirected
}
// A recursive function that returns true if there is an articulation
// point in given graph, otherwise returns false.
// This function is almost same as isAPUtil() here ( http://goo.gl/Me9Fw )
// u --> The vertex to be visited next
// visited[] --> keeps tract of visited vertices
// disc[] --> Stores discovery times of visited vertices
// parent[] --> Stores parent vertices in DFS tree
bool Graph::isBCUtil(int u, bool visited[], int disc[],int low[],int parent[])
{
// A static variable is used for simplicity, we can avoid use of static
// variable by passing a pointer.
static int time = 0;
// Count of children in DFS Tree
int children = 0;
// Mark the current node as visited
visited[u] = true;
// Initialize discovery time and low value
disc[u] = low[u] = ++time;
// Go through all vertices aadjacent to this
list<int>::iterator i;
for (i = adj[u].begin(); i != adj[u].end(); ++i)
{
int v = *i; // v is current adjacent of u
// If v is not visited yet, then make it a child of u
// in DFS tree and recur for it
if (!visited[v])
{
children++;
parent[v] = u;
// check if subgraph rooted with v has an articulation point
375
Chapter 44. Biconnected graph
376
Chapter 44. Biconnected graph
// Now check whether the given graph is connected or not. An undirected
// graph is connected if all vertices are reachable from any starting
// point (we have taken 0 as starting point)
for (int i = 0; i < V; i++)
if (visited[i] == false)
return false;
return true;
}
// Driver program to test above function
int main()
{
// Create graphs given in above diagrams
Graph g1(2);
g1.addEdge(0, 1);
g1.isBC()? cout << "Yes\n" : cout << "No\n";
Graph g2(5);
g2.addEdge(1, 0);
g2.addEdge(0, 2);
g2.addEdge(2, 1);
g2.addEdge(0, 3);
g2.addEdge(3, 4);
g2.addEdge(2, 4);
g2.isBC()? cout << "Yes\n" : cout << "No\n";
Graph g3(3);
g3.addEdge(0, 1);
g3.addEdge(1, 2);
g3.isBC()? cout << "Yes\n" : cout << "No\n";
Graph g4(5);
g4.addEdge(1, 0);
g4.addEdge(0, 2);
g4.addEdge(2, 1);
g4.addEdge(0, 3);
g4.addEdge(3, 4);
g4.isBC()? cout << "Yes\n" : cout << "No\n";
Graph g5(3);
g5.addEdge(0, 1);
g5.addEdge(1, 2);
g5.addEdge(2, 0);
g5.isBC()? cout << "Yes\n" : cout << "No\n";
return 0;
377
Chapter 44. Biconnected graph
Java
378
Chapter 44. Biconnected graph
// Count of children in DFS Tree
int children = 0;
// Mark the current node as visited
visited[u] = true;
// Initialize discovery time and low value
disc[u] = low[u] = ++time;
// Go through all vertices aadjacent to this
Iterator<Integer> i = adj[u].iterator();
while (i.hasNext())
{
int v = i.next(); // v is current adjacent of u
// If v is not visited yet, then make it a child of u
// in DFS tree and recur for it
if (!visited[v])
{
children++;
parent[v] = u;
// check if subgraph rooted with v has an articulation point
if (isBCUtil(v, visited, disc, low, parent))
return true;
// Check if the subtree rooted with v has a connection to
// one of the ancestors of u
low[u] = Math.min(low[u], low[v]);
// u is an articulation point in following cases
// (1) u is root of DFS tree and has two or more chilren.
if (parent[u] == NIL && children > 1)
return true;
// (2) If u is not root and low value of one of its
// child is more than discovery value of u.
if (parent[u] != NIL && low[v] >= disc[u])
return true;
}
// Update low value of u for parent function calls.
else if (v != parent[u])
low[u] = Math.min(low[u], disc[v]);
}
return false;
379
Chapter 44. Biconnected graph
}
// The main function that returns true if graph is Biconnected,
// otherwise false. It uses recursive function isBCUtil()
boolean isBC()
{
// Mark all the vertices as not visited
boolean visited[] = new boolean[V];
int disc[] = new int[V];
int low[] = new int[V];
int parent[] = new int[V];
// Initialize parent and visited, and ap(articulation point)
// arrays
for (int i = 0; i < V; i++)
{
parent[i] = NIL;
visited[i] = false;
}
// Call the recursive helper function to find if there is an
// articulation/ point in given graph. We do DFS traversal
// starring from vertex 0
if (isBCUtil(0, visited, disc, low, parent) == true)
return false;
// Now check whether the given graph is connected or not.
// An undirected graph is connected if all vertices are
// reachable from any starting point (we have taken 0 as
// starting point)
for (int i = 0; i < V; i++)
if (visited[i] == false)
return false;
return true;
}
// Driver method
public static void main(String args[])
{
// Create graphs given in above diagrams
Graph g1 =new Graph(2);
g1.addEdge(0, 1);
if (g1.isBC())
System.out.println("Yes");
else
System.out.println("No");
380
Chapter 44. Biconnected graph
Python
381
Chapter 44. Biconnected graph
382
Chapter 44. Biconnected graph
# u is an articulation point in following cases
# (1) u is root of DFS tree and has two or more chilren.
if parent[u] == -1 and children > 1:
return True
#(2) If u is not root and low value of one of its child is more
# than discovery value of u.
if parent[u] != -1 and low[v] >= disc[u]:
return True
elif v != parent[u]: # Update low value of u for parent function calls.
low[u] = min(low[u], disc[v])
return False
# The main function that returns true if graph is Biconnected,
# otherwise false. It uses recursive function isBCUtil()
def isBC(self):
# Mark all the vertices as not visited and Initialize parent and visited,
# and ap(articulation point) arrays
visited = [False] * (self.V)
disc = [float("Inf")] * (self.V)
low = [float("Inf")] * (self.V)
parent = [-1] * (self.V)
# Call the recursive helper function to find if there is an
# articulation points in given graph. We do DFS traversal starting
# from vertex 0
if self.isBCUtil(0, visited, parent, low, disc):
return False
'''Now check whether the given graph is connected or not.
An undirected graph is connected if all vertices are
reachable from any starting point (we have taken 0 as
starting point)'''
if any(i == False for i in visited):
return False
return True
# Create a graph given in the above diagram
g1 = Graph(2)
g1.addEdge(0, 1)
print "Yes" if g1.isBC() else "No"
383
Chapter 44. Biconnected graph
g2 = Graph(5)
g2.addEdge(1, 0)
g2.addEdge(0, 2)
g2.addEdge(2, 1)
g2.addEdge(0, 3)
g2.addEdge(3, 4)
g2.addEdge(2, 4)
print "Yes" if g2.isBC() else "No"
g3 = Graph(3)
g3.addEdge(0, 1)
g3.addEdge(1, 2)
print "Yes" if g3.isBC() else "No"
g4 = Graph (5)
g4.addEdge(1, 0)
g4.addEdge(0, 2)
g4.addEdge(2, 1)
g4.addEdge(0, 3)
g4.addEdge(3, 4)
print "Yes" if g4.isBC() else "No"
g5 = Graph(3)
g5.addEdge(0, 1)
g5.addEdge(1, 2)
g5.addEdge(2, 0)
print "Yes" if g5.isBC() else "No"
#This code is contributed by Neelam Yadav
Output:
Yes
Yes
No
No
Yes
Time Complexity: The above function is a simple DFS with additional arrays. So time
complexity is same as DFS which is O(V+E) for adjacency list representation of graph.
References:
http://www.cs.purdue.edu/homes/ayg/CS251/slides/chap9d.pdf
384
Chapter 44. Biconnected graph
Source
https://www.geeksforgeeks.org/biconnectivity-in-a-graph/
385
Chapter 45
Bridges in a graph
386
Chapter 45. Bridges in a graph
387
Chapter 45. Bridges in a graph
388
Chapter 45. Bridges in a graph
389
Chapter 45. Bridges in a graph
g3.bridge();
return 0;
}
Java
390
Chapter 45. Bridges in a graph
// Mark the current node as visited
visited[u] = true;
// Initialize discovery time and low value
disc[u] = low[u] = ++time;
// Go through all vertices aadjacent to this
Iterator<Integer> i = adj[u].iterator();
while (i.hasNext())
{
int v = i.next(); // v is current adjacent of u
// If v is not visited yet, then make it a child
// of u in DFS tree and recur for it.
// If v is not visited yet, then recur for it
if (!visited[v])
{
parent[v] = u;
bridgeUtil(v, visited, disc, low, parent);
// Check if the subtree rooted with v has a
// connection to one of the ancestors of u
low[u] = Math.min(low[u], low[v]);
// If the lowest vertex reachable from subtree
// under v is below u in DFS tree, then u-v is
// a bridge
if (low[v] > disc[u])
System.out.println(u+" "+v);
}
// Update low value of u for parent function calls.
else if (v != parent[u])
low[u] = Math.min(low[u], disc[v]);
}
}
// DFS based function to find all bridges. It uses recursive
// function bridgeUtil()
void bridge()
{
// Mark all the vertices as not visited
boolean visited[] = new boolean[V];
int disc[] = new int[V];
int low[] = new int[V];
int parent[] = new int[V];
391
Chapter 45. Bridges in a graph
// Initialize parent and visited, and ap(articulation point)
// arrays
for (int i = 0; i < V; i++)
{
parent[i] = NIL;
visited[i] = false;
}
// Call the recursive helper function to find Bridges
// in DFS tree rooted with vertex 'i'
for (int i = 0; i < V; i++)
if (visited[i] == false)
bridgeUtil(i, visited, disc, low, parent);
}
public static void main(String args[])
{
// Create graphs given in above diagrams
System.out.println("Bridges in first graph ");
Graph g1 = new Graph(5);
g1.addEdge(1, 0);
g1.addEdge(0, 2);
g1.addEdge(2, 1);
g1.addEdge(0, 3);
g1.addEdge(3, 4);
g1.bridge();
System.out.println();
System.out.println("Bridges in Second graph");
Graph g2 = new Graph(4);
g2.addEdge(0, 1);
g2.addEdge(1, 2);
g2.addEdge(2, 3);
g2.bridge();
System.out.println();
System.out.println("Bridges in Third graph ");
Graph g3 = new Graph(7);
g3.addEdge(0, 1);
g3.addEdge(1, 2);
g3.addEdge(2, 0);
g3.addEdge(1, 3);
g3.addEdge(1, 4);
g3.addEdge(1, 6);
g3.addEdge(3, 5);
g3.addEdge(4, 5);
392
Chapter 45. Bridges in a graph
g3.bridge();
}
}
// This code is contributed by Aakash Hasija
Python
393
Chapter 45. Bridges in a graph
# Check if the subtree rooted with v has a connection to
# one of the ancestors of u
low[u] = min(low[u], low[v])
''' If the lowest vertex reachable from subtree
under v is below u in DFS tree, then u-v is
a bridge'''
if low[v] > disc[u]:
print ("%d %d" %(u,v))
elif v != parent[u]: # Update low value of u for parent function calls.
low[u] = min(low[u], disc[v])
# DFS based function to find all bridges. It uses recursive
# function bridgeUtil()
def bridge(self):
# Mark all the vertices as not visited and Initialize parent and visited,
# and ap(articulation point) arrays
visited = [False] * (self.V)
disc = [float("Inf")] * (self.V)
low = [float("Inf")] * (self.V)
parent = [-1] * (self.V)
# Call the recursive helper function to find bridges
# in DFS tree rooted with vertex 'i'
for i in range(self.V):
if visited[i] == False:
self.bridgeUtil(i, visited, parent, low, disc)
# Create a graph given in the above diagram
g1 = Graph(5)
g1.addEdge(1, 0)
g1.addEdge(0, 2)
g1.addEdge(2, 1)
g1.addEdge(0, 3)
g1.addEdge(3, 4)
print "Bridges in first graph "
g1.bridge()
g2 = Graph(4)
394
Chapter 45. Bridges in a graph
g2.addEdge(0, 1)
g2.addEdge(1, 2)
g2.addEdge(2, 3)
print "\nBridges in second graph "
g2.bridge()
g3 = Graph (7)
g3.addEdge(0, 1)
g3.addEdge(1, 2)
g3.addEdge(2, 0)
g3.addEdge(1, 3)
g3.addEdge(1, 4)
g3.addEdge(1, 6)
g3.addEdge(3, 5)
g3.addEdge(4, 5)
print "\nBridges in third graph "
g3.bridge()
#This code is contributed by Neelam Yadav
Output:
Time Complexity: The above function is simple DFS with additional arrays. So time
complexity is same as DFS which is O(V+E) for adjacency list representation of graph.
References:
https://www.cs.washington.edu/education/courses/421/04su/slides/artic.pdf
http://www.slideshare.net/TraianRebedea/algorithm-design-and-complexity-course-8
http://faculty.simpson.edu/lydia.sinapova/www/cmsc250/LN250_Weiss/L25-Connectivity.
htm
http://www.youtube.com/watch?v=bmyyxNyZKzI
Please write comments if you find anything incorrect, or you want to share more information
about the topic discussed above.
Improved By : FurqanAziz, MatthiasKoerber
395
Chapter 45. Bridges in a graph
Source
https://www.geeksforgeeks.org/bridge-in-a-graph/
396
Chapter 46
397
Chapter 46. Eulerian path and circuit
398
Chapter 46. Eulerian path and circuit
class Graph
{
int V; // No. of vertices
list<int> *adj; // A dynamic array of adjacency lists
public:
// Constructor and destructor
Graph(int V) {this->V = V; adj = new list<int>[V]; }
~Graph() { delete [] adj; } // To avoid memory leak
// function to add an edge to graph
void addEdge(int v, int w);
// Method to check if this graph is Eulerian or not
int isEulerian();
// Method to check if all non-zero degree vertices are connected
bool isConnected();
// Function to do DFS starting from v. Used in isConnected();
void DFSUtil(int v, bool visited[]);
};
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w);
adj[w].push_back(v); // Note: the graph is undirected
}
void Graph::DFSUtil(int v, bool visited[])
{
// Mark the current node as visited and print it
visited[v] = true;
// Recur for all the vertices adjacent to this vertex
list<int>::iterator i;
for (i = adj[v].begin(); i != adj[v].end(); ++i)
if (!visited[*i])
DFSUtil(*i, visited);
}
// Method to check if all non-zero degree vertices are connected.
// It mainly does DFS traversal starting from
bool Graph::isConnected()
{
// Mark all the vertices as not visited
bool visited[V];
int i;
for (i = 0; i < V; i++)
399
Chapter 46. Eulerian path and circuit
visited[i] = false;
// Find a vertex with non-zero degree
for (i = 0; i < V; i++)
if (adj[i].size() != 0)
break;
// If there are no edges in the graph, return true
if (i == V)
return true;
// Start DFS traversal from a vertex with non-zero degree
DFSUtil(i, visited);
// Check if all non-zero degree vertices are visited
for (i = 0; i < V; i++)
if (visited[i] == false && adj[i].size() > 0)
return false;
return true;
}
/* The function returns one of the following values
0 --> If grpah is not Eulerian
1 --> If graph has an Euler path (Semi-Eulerian)
2 --> If graph has an Euler Circuit (Eulerian) */
int Graph::isEulerian()
{
// Check if all non-zero degree vertices are connected
if (isConnected() == false)
return 0;
// Count vertices with odd degree
int odd = 0;
for (int i = 0; i < V; i++)
if (adj[i].size() & 1)
odd++;
// If count is more than 2, then graph is not Eulerian
if (odd > 2)
return 0;
// If odd count is 2, then semi-eulerian.
// If odd count is 0, then eulerian
// Note that odd count can never be 1 for undirected graph
return (odd)? 1 : 2;
}
400
Chapter 46. Eulerian path and circuit
401
Chapter 46. Eulerian path and circuit
test(g4);
// Let us create a graph with all veritces
// with zero degree
Graph g5(3);
test(g5);
return 0;
}
Java
402
Chapter 46. Eulerian path and circuit
403
Chapter 46. Eulerian path and circuit
return 0;
// Count vertices with odd degree
int odd = 0;
for (int i = 0; i < V; i++)
if (adj[i].size()%2!=0)
odd++;
// If count is more than 2, then graph is not Eulerian
if (odd > 2)
return 0;
// If odd count is 2, then semi-eulerian.
// If odd count is 0, then eulerian
// Note that odd count can never be 1 for undirected graph
return (odd==2)? 1 : 2;
}
// Function to run test cases
void test()
{
int res = isEulerian();
if (res == 0)
System.out.println("graph is not Eulerian");
else if (res == 1)
System.out.println("graph has a Euler path");
else
System.out.println("graph has a Euler cycle");
}
// Driver method
public static void main(String args[])
{
// Let us create and test graphs shown in above figures
Graph g1 = new Graph(5);
g1.addEdge(1, 0);
g1.addEdge(0, 2);
g1.addEdge(2, 1);
g1.addEdge(0, 3);
g1.addEdge(3, 4);
g1.test();
Graph g2 = new Graph(5);
g2.addEdge(1, 0);
g2.addEdge(0, 2);
g2.addEdge(2, 1);
g2.addEdge(0, 3);
g2.addEdge(3, 4);
404
Chapter 46. Eulerian path and circuit
g2.addEdge(4, 0);
g2.test();
Graph g3 = new Graph(5);
g3.addEdge(1, 0);
g3.addEdge(0, 2);
g3.addEdge(2, 1);
g3.addEdge(0, 3);
g3.addEdge(3, 4);
g3.addEdge(1, 3);
g3.test();
// Let us create a graph with 3 vertices
// connected in the form of cycle
Graph g4 = new Graph(3);
g4.addEdge(0, 1);
g4.addEdge(1, 2);
g4.addEdge(2, 0);
g4.test();
// Let us create a graph with all veritces
// with zero degree
Graph g5 = new Graph(3);
g5.test();
}
}
// This code is contributed by Aakash Hasija
Python
405
Chapter 46. Eulerian path and circuit
def DFSUtil(self,v,visited):
# Mark the current node as visited
visited[v]= True
#Recur for all the vertices adjacent to this vertex
for i in self.graph[v]:
if visited[i]==False:
self.DFSUtil(i,visited)
'''Method to check if all non-zero degree vertices are
connected. It mainly does DFS traversal starting from
node with non-zero degree'''
def isConnected(self):
# Mark all the vertices as not visited
visited =[False]*(self.V)
# Find a vertex with non-zero degree
for i in range(self.V):
if len(self.graph[i]) > 1:
break
# If there are no edges in the graph, return true
if i == self.V-1:
return True
# Start DFS traversal from a vertex with non-zero degree
self.DFSUtil(i,visited)
# Check if all non-zero degree vertices are visited
for i in range(self.V):
if visited[i]==False and len(self.graph[i]) > 0:
return False
return True
'''The function returns one of the following values
0 --> If grpah is not Eulerian
1 --> If graph has an Euler path (Semi-Eulerian)
2 --> If graph has an Euler Circuit (Eulerian) '''
def isEulerian(self):
# Check if all non-zero degree vertices are connected
if self.isConnected() == False:
return 0
else:
#Count vertices with odd degree
406
Chapter 46. Eulerian path and circuit
odd = 0
for i in range(self.V):
if len(self.graph[i]) % 2 !=0:
odd +=1
'''If odd count is 2, then semi-eulerian.
If odd count is 0, then eulerian
If count is more than 2, then graph is not Eulerian
Note that odd count can never be 1 for undirected graph'''
if odd == 0:
return 2
elif odd == 2:
return 1
elif odd > 2:
return 0
# Function to run test cases
def test(self):
res = self.isEulerian()
if res == 0:
print "graph is not Eulerian"
elif res ==1 :
print "graph has a Euler path"
else:
print "graph has a Euler cycle"
#Let us create and test graphs shown in above figures
g1 = Graph(5);
g1.addEdge(1, 0)
g1.addEdge(0, 2)
g1.addEdge(2, 1)
g1.addEdge(0, 3)
g1.addEdge(3, 4)
g1.test()
g2 = Graph(5)
g2.addEdge(1, 0)
g2.addEdge(0, 2)
g2.addEdge(2, 1)
g2.addEdge(0, 3)
g2.addEdge(3, 4)
g2.addEdge(4, 0)
g2.test();
g3 = Graph(5)
407
Chapter 46. Eulerian path and circuit
g3.addEdge(1, 0)
g3.addEdge(0, 2)
g3.addEdge(2, 1)
g3.addEdge(0, 3)
g3.addEdge(3, 4)
g3.addEdge(1, 3)
g3.test()
#Let us create a graph with 3 vertices
# connected in the form of cycle
g4 = Graph(3)
g4.addEdge(0, 1)
g4.addEdge(1, 2)
g4.addEdge(2, 0)
g4.test()
# Let us create a graph with all veritces
# with zero degree
g5 = Graph(3)
g5.test()
#This code is contributed by Neelam Yadav
Output:
Source
https://www.geeksforgeeks.org/eulerian-path-and-circuit/
408
Chapter 47
409
Chapter 47. Fleury’s Algorithm for printing Eulerian Path or Circuit
There are two vertices with odd degree, ‘2’ and ‘3’, we can start path from any of them. Let
us start tour from vertex ‘2’.
There are three edges going out from vertex ‘2’, which one to pick? We don’t pick the edge
‘2-3’ because that is a bridge (we won’t be able to come back to ‘3’). We can pick any of the
remaining two edge. Let us say we pick ‘2-0’. We remove this edge and move to vertex ‘0’.
There is only one edge from vertex ‘0’, so we pick it, remove it and move to vertex ‘1’. Euler
tour becomes ‘2-0 0-1’.
There is only one edge from vertex ‘1’, so we pick it, remove it and move to vertex ‘2’. Euler
tour becomes ‘2-0 0-1 1-2’
Again there is only one edge from vertex 2, so we pick it, remove it and move to vertex 3.
Euler tour becomes ‘2-0 0-1 1-2 2-3’
410
Chapter 47. Fleury’s Algorithm for printing Eulerian Path or Circuit
There are no more edges left, so we stop here. Final tour is ‘2-0 0-1 1-2 2-3’.
See thisfor and thisfore more examples.
Following is C++ implementation of above algorithm. In the following code, it is assumed
that the given graph has an Eulerian trail or Circuit. The main focus is to print an Eulerian
trail or circuit. We can use isEulerian() to first check whether there is an Eulerian Trail or
Circuit in the given graph.
We first find the starting point which must be an odd vertex (if there are odd vertices) and
store it in variable ‘u’. If there are zero odd vertices, we start from vertex ‘0’. We call
printEulerUtil() to print Euler tour starting with u. We traverse all adjacent vertices of u,
if there is only one adjacent vertex, we immediately consider it. If there are more than one
adjacent vertices, we consider an adjacent v only if edge u-v is not a bridge. How to find if
a given is edge is bridge? We count number of vertices reachable from u. We remove edge
u-v and again count number of reachable vertices from u. If number of reachable vertices
are reduced, then edge u-v is a bridge. To count reachable vertices, we can either use BFS
or DFS, we have used DFS in the above code. The function DFSCount(u) returns number
of vertices reachable from u.
Once an edge is processed (included in Euler tour), we remove it from the graph. To remove
the edge, we replace the vertex entry with -1 in adjacency list. Note that simply deleting the
node may not work as the code is recursive and a parent call may be in middle of adjacency
list.
C/C++
411
Chapter 47. Fleury’s Algorithm for printing Eulerian Path or Circuit
412
Chapter 47. Fleury’s Algorithm for printing Eulerian Path or Circuit
printEulerUtil(v);
}
}
}
// The function to check if edge u-v can be considered as next edge in
// Euler Tout
bool Graph::isValidNextEdge(int u, int v)
{
// The edge u-v is valid in one of the following two cases:
// 1) If v is the only adjacent vertex of u
int count = 0; // To store count of adjacent vertices
list<int>::iterator i;
for (i = adj[u].begin(); i != adj[u].end(); ++i)
if (*i != -1)
count++;
if (count == 1)
return true;
// 2) If there are multiple adjacents, then u-v is not a bridge
// Do following steps to check if u-v is a bridge
// 2.a) count of vertices reachable from u
bool visited[V];
memset(visited, false, V);
int count1 = DFSCount(u, visited);
// 2.b) Remove edge (u, v) and after removing the edge, count
// vertices reachable from u
rmvEdge(u, v);
memset(visited, false, V);
int count2 = DFSCount(u, visited);
// 2.c) Add the edge back to the graph
addEdge(u, v);
// 2.d) If count1 is greater, then edge (u, v) is a bridge
return (count1 > count2)? false: true;
}
// This function removes edge u-v from graph. It removes the edge by
// replacing adjcent vertex value with -1.
void Graph::rmvEdge(int u, int v)
{
// Find v in adjacency list of u and replace it with -1
list<int>::iterator iv = find(adj[u].begin(), adj[u].end(), v);
413
Chapter 47. Fleury’s Algorithm for printing Eulerian Path or Circuit
*iv = -1;
// Find u in adjacency list of v and replace it with -1
list<int>::iterator iu = find(adj[v].begin(), adj[v].end(), u);
*iu = -1;
}
// A DFS based function to count reachable vertices from v
int Graph::DFSCount(int v, bool visited[])
{
// Mark the current node as visited
visited[v] = true;
int count = 1;
// Recur for all vertices adjacent to this vertex
list<int>::iterator i;
for (i = adj[v].begin(); i != adj[v].end(); ++i)
if (*i != -1 && !visited[*i])
count += DFSCount(*i, visited);
return count;
}
// Driver program to test above function
int main()
{
// Let us first create and test graphs shown in above figure
Graph g1(4);
g1.addEdge(0, 1);
g1.addEdge(0, 2);
g1.addEdge(1, 2);
g1.addEdge(2, 3);
g1.printEulerTour();
Graph g2(3);
g2.addEdge(0, 1);
g2.addEdge(1, 2);
g2.addEdge(2, 0);
g2.printEulerTour();
Graph g3(5);
g3.addEdge(1, 0);
g3.addEdge(0, 2);
g3.addEdge(2, 1);
g3.addEdge(0, 3);
g3.addEdge(3, 4);
g3.addEdge(3, 2);
g3.addEdge(3, 1);
414
Chapter 47. Fleury’s Algorithm for printing Eulerian Path or Circuit
g3.addEdge(2, 4);
g3.printEulerTour();
return 0;
}
Java
415
Chapter 47. Fleury’s Algorithm for printing Eulerian Path or Circuit
416
Chapter 47. Fleury’s Algorithm for printing Eulerian Path or Circuit
417
Chapter 47. Fleury’s Algorithm for printing Eulerian Path or Circuit
Python
418
Chapter 47. Fleury’s Algorithm for printing Eulerian Path or Circuit
def addEdge(self,u,v):
self.graph[u].append(v)
self.graph[v].append(u)
# This function removes edge u-v from graph
def rmvEdge(self, u, v):
for index, key in enumerate(self.graph[u]):
if key == v:
self.graph[u].pop(index)
for index, key in enumerate(self.graph[v]):
if key == u:
self.graph[v].pop(index)
# A DFS based function to count reachable vertices from v
def DFSCount(self, v, visited):
count = 1
visited[v] = True
for i in self.graph[v]:
if visited[i] == False:
count = count + self.DFSCount(i, visited)
return count
# The function to check if edge u-v can be considered as next edge in
# Euler Tour
def isValidNextEdge(self, u, v):
# The edge u-v is valid in one of the following two cases:
# 1) If v is the only adjacent vertex of u
if len(self.graph[u]) == 1:
return True
else:
'''
2) If there are multiple adjacents, then u-v is not a bridge
Do following steps to check if u-v is a bridge
2.a) count of vertices reachable from u'''
visited =[False]*(self.V)
count1 = self.DFSCount(u, visited)
'''2.b) Remove edge (u, v) and after removing the edge, count
vertices reachable from u'''
self.rmvEdge(u, v)
visited =[False]*(self.V)
count2 = self.DFSCount(u, visited)
#2.c) Add the edge back to the graph
self.addEdge(u,v)
419
Chapter 47. Fleury’s Algorithm for printing Eulerian Path or Circuit
420
Chapter 47. Fleury’s Algorithm for printing Eulerian Path or Circuit
g3.addEdge(0, 2)
g3.addEdge(2, 1)
g3.addEdge(0, 3)
g3.addEdge(3, 4)
g3.addEdge(3, 2)
g3.addEdge(3, 1)
g3.addEdge(2, 4)
g3.printEulerTour()
#This code is contributed by Neelam Yadav
Output:
Note that the above code modifies given graph, we can create a copy of graph if we don’t
want the given graph to be modified.
Time Complexity: Time complexity of the above implementation is O ((V+E)2 ). The
function printEulerUtil() is like DFS and it calls isValidNextEdge() which also does DFS
two times. Time complexity of DFS for adjacency list representation is O(V+E). Therefore
overall time complexity is O((V+E)*(V+E)) which can be written as O(E2 ) for a connected
graph.
There are better algorithms to print Euler tour, Hierholzer’s Algorithm finds in O(V+E)
time.
References:
http://www.math.ku.edu/~jmartin/courses/math105-F11/Lectures/chapter5-part2.pdf
http://en.wikipedia.org/wiki/Eulerian_path#Fleury.27s_algorithm
Source
https://www.geeksforgeeks.org/fleurys-algorithm-for-printing-eulerian-path/
421
Chapter 48
Strongly Connected
Components
We can find all strongly connected components in O(V+E) time using Kosaraju’s algorithm.
Following is detailed Kosaraju’s algorithm.
1) Create an empty stack ‘S’ and do DFS traversal of a graph. In DFS traversal, after
calling recursive DFS for adjacent vertices of a vertex, push the vertex to stack. In the
above graph, if we start DFS from vertex 0, we get vertices in stack as 1, 2, 4, 3, 0.
2) Reverse directions of all arcs to obtain the transpose graph.
3) One by one pop a vertex from S while S is not empty. Let the popped vertex be ‘v’.
422
Chapter 48. Strongly Connected Components
Take v as source and do DFS (call DFSUtil(v)). The DFS starting from v prints strongly
connected component of v. In the above example, we process vertices in order 0, 3, 4, 2, 1
(One by one popped from stack).
How does this work?
The above algorithm is DFS based. It does DFS two times. DFS of a graph produces a
single tree if all vertices are reachable from the DFS starting point. Otherwise DFS produces
a forest. So DFS of a graph with only one SCC always produces a tree. The important
point to note is DFS may produce a tree or a forest when there are more than one SCCs
depending upon the chosen starting point. For example, in the above diagram, if we start
DFS from vertices 0 or 1 or 2, we get a tree as output. And if we start from 3 or 4, we get
a forest. To find and print all SCCs, we would want to start DFS from vertex 4 (which is a
sink vertex), then move to 3 which is sink in the remaining set (set excluding 4) and finally
any of the remaining vertices (0, 1, 2). So how do we find this sequence of picking vertices
as starting points of DFS? Unfortunately, there is no direct way for getting this sequence.
However, if we do a DFS of graph and store vertices according to their finish times, we make
sure that the finish time of a vertex that connects to other SCCs (other that its own SCC),
will always be greater than finish time of vertices in the other SCC (See thisfor proof). For
example, in DFS of above example graph, finish time of 0 is always greater than 3 and 4
(irrespective of the sequence of vertices considered for DFS). And finish time of 3 is always
greater than 4. DFS doesn’t guarantee about other vertices, for example finish times of
1 and 2 may be smaller or greater than 3 and 4 depending upon the sequence of vertices
considered for DFS. So to use this property, we do DFS traversal of complete graph and
push every finished vertex to a stack. In stack, 3 always appears after 4, and 0 appear after
both 3 and 4.
In the next step, we reverse the graph. Consider the graph of SCCs. In the reversed graph,
the edges that connect two components are reversed. So the SCC {0, 1, 2} becomes sink
and the SCC {4} becomes source. As discussed above, in stack, we always have 0 before
3 and 4. So if we do a DFS of the reversed graph using sequence of vertices in stack, we
process vertices from sink to source (in reversed graph). That is what we wanted to achieve
and that is all needed to print SCCs one by one.
423
Chapter 48. Strongly Connected Components
#include <iostream>
#include <list>
#include <stack>
using namespace std;
class Graph
{
int V; // No. of vertices
list<int> *adj; // An array of adjacency lists
// Fills Stack with vertices (in increasing order of finishing
// times). The top element of stack has the maximum finishing
// time
void fillOrder(int v, bool visited[], stack<int> &Stack);
// A recursive function to print DFS starting from v
void DFSUtil(int v, bool visited[]);
public:
Graph(int V);
void addEdge(int v, int w);
// The main function that finds and prints strongly connected
// components
void printSCCs();
// Function that returns reverse (or transpose) of this graph
Graph getTranspose();
};
Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V];
}
// A recursive function to print DFS starting from v
void Graph::DFSUtil(int v, bool visited[])
{
// Mark the current node as visited and print it
visited[v] = true;
cout << v << " ";
// Recur for all the vertices adjacent to this vertex
list<int>::iterator i;
for (i = adj[v].begin(); i != adj[v].end(); ++i)
if (!visited[*i])
DFSUtil(*i, visited);
}
424
Chapter 48. Strongly Connected Components
Graph Graph::getTranspose()
{
Graph g(V);
for (int v = 0; v < V; v++)
{
// Recur for all the vertices adjacent to this vertex
list<int>::iterator i;
for(i = adj[v].begin(); i != adj[v].end(); ++i)
{
g.adj[*i].push_back(v);
}
}
return g;
}
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w); // Add w to v’s list.
}
void Graph::fillOrder(int v, bool visited[], stack<int> &Stack)
{
// Mark the current node as visited and print it
visited[v] = true;
// Recur for all the vertices adjacent to this vertex
list<int>::iterator i;
for(i = adj[v].begin(); i != adj[v].end(); ++i)
if(!visited[*i])
fillOrder(*i, visited, Stack);
// All vertices reachable from v are processed by now, push v
Stack.push(v);
}
// The main function that finds and prints all strongly connected
// components
void Graph::printSCCs()
{
stack<int> Stack;
// Mark all the vertices as not visited (For first DFS)
bool *visited = new bool[V];
for(int i = 0; i < V; i++)
visited[i] = false;
// Fill vertices in stack according to their finishing times
425
Chapter 48. Strongly Connected Components
Java
426
Chapter 48. Strongly Connected Components
import java.io.*;
import java.util.*;
import java.util.LinkedList;
// This class represents a directed graph using adjacency list
// representation
class Graph
{
private int V; // No. of vertices
private LinkedList<Integer> adj[]; //Adjacency List
//Constructor
Graph(int v)
{
V = v;
adj = new LinkedList[v];
for (int i=0; i<v; ++i)
adj[i] = new LinkedList();
}
//Function to add an edge into the graph
void addEdge(int v, int w) { adj[v].add(w); }
// A recursive function to print DFS starting from v
void DFSUtil(int v,boolean visited[])
{
// Mark the current node as visited and print it
visited[v] = true;
System.out.print(v + " ");
int n;
// Recur for all the vertices adjacent to this vertex
Iterator<Integer> i =adj[v].iterator();
while (i.hasNext())
{
n = i.next();
if (!visited[n])
DFSUtil(n,visited);
}
}
// Function that returns reverse (or transpose) of this graph
Graph getTranspose()
{
Graph g = new Graph(V);
for (int v = 0; v < V; v++)
{
427
Chapter 48. Strongly Connected Components
428
Chapter 48. Strongly Connected Components
Python
429
Chapter 48. Strongly Connected Components
# function to add an edge to graph
def addEdge(self,u,v):
self.graph[u].append(v)
# A function used by DFS
def DFSUtil(self,v,visited):
# Mark the current node as visited and print it
visited[v]= True
print v,
#Recur for all the vertices adjacent to this vertex
for i in self.graph[v]:
if visited[i]==False:
self.DFSUtil(i,visited)
def fillOrder(self,v,visited, stack):
# Mark the current node as visited
visited[v]= True
#Recur for all the vertices adjacent to this vertex
for i in self.graph[v]:
if visited[i]==False:
self.fillOrder(i, visited, stack)
stack = stack.append(v)
# Function that returns reverse (or transpose) of this graph
def getTranspose(self):
g = Graph(self.V)
# Recur for all the vertices adjacent to this vertex
for i in self.graph:
for j in self.graph[i]:
g.addEdge(j,i)
return g
# The main function that finds and prints all strongly
# connected components
def printSCCs(self):
stack = []
# Mark all the vertices as not visited (For first DFS)
visited =[False]*(self.V)
# Fill vertices in stack according to their finishing
# times
for i in range(self.V):
430
Chapter 48. Strongly Connected Components
if visited[i]==False:
self.fillOrder(i, visited, stack)
# Create a reversed graph
gr = self.getTranspose()
# Mark all the vertices as not visited (For second DFS)
visited =[False]*(self.V)
# Now process all vertices in order defined by Stack
while stack:
i = stack.pop()
if visited[i]==False:
gr.DFSUtil(i, visited)
print""
# Create a graph given in the above diagram
g = Graph(5)
g.addEdge(1, 0)
g.addEdge(0, 2)
g.addEdge(2, 1)
g.addEdge(0, 3)
g.addEdge(3, 4)
print ("Following are strongly connected components " +
"in given graph")
g.printSCCs()
#This code is contributed by Neelam Yadav
Output:
Time Complexity: The above algorithm calls DFS, fins reverse of the graph and again
calls DFS. DFS takes O(V+E) for a graph represented using adjacency list. Reversing a
graph also takes O(V+E) time. For reversing the graph, we simple traverse all adjacency
lists.
The above algorithm is asymptotically best algorithm, but there are other algorithms like
Tarjan’s algorithm and path-based which have same time complexity but find SCCs using
single DFS. The Tarjan’s algorithm is discussed in the following post.
Tarjan’s Algorithm to find Strongly Connected Components
Applications:
SCC algorithms can be used as a first step in many graph algorithms that work only on
431
Chapter 48. Strongly Connected Components
Source
https://www.geeksforgeeks.org/strongly-connected-components/
432
Chapter 49
We have discussed Kosaraju’s algorithm for strongly connected components. The previously
discussed algorithm requires two DFS traversals of a Graph. In this post, Tarjan’s algorithm
is discussed that requires only one DFS traversal.
Tarjan Algorithm is based on following facts:
1. DFS search produces a DFS tree/forest
2. Strongly Connected Components form subtrees of the DFS tree.
3. If we can find head of such subtrees, we can print/store all the nodes in that subtree
433
Chapter 49. Tarjan’s Algorithm to find Strongly Connected Components
Strongly Connected Component relates to directed graph only, but Disc and Low values
434
Chapter 49. Tarjan’s Algorithm to find Strongly Connected Components
relate to both directed and undirected graph, so in above pic we have taken an undirected
graph.
In above Figure, we have shown a graph and it’s one of DFS tree (There could be different
DFS trees on same graph depending on order in which edges are traversed).
In DFS tree, continuous arrows are tree edges and dashed arrows are back edges (DFS Tree
Edges
Disc and Low values are showin in Figure for every node as (Disc/Low).
Disc: This is the time when a node is visited 1st time while DFS traversal. For nodes A,
B, C, .., J in DFS tree, Disc values are 1, 2, 3, .., 10.
Low: In DFS tree, Tree edges take us forward, from ancestor node to one of it’s descendants.
For example, from node C, tree edges can take us to node node G, node I etc. Back edges
take us backward, from a descendant node to one of it’s ancestors. For example, from node
G, Back edges take us to E or C. If we look at both Tree and Back edge together, then we
can see that if we start traversal from one node, we may go down the tree via Tree edges
and then go up via back edges. For example, from node E, we can go down to G and then
go up to C. Similarly from E, we can go down to I or J and then go up to F. “Low” value
of a node tells the topmost reachable ancestor (with minimum possible Disc value) via the
subtree of that node. So for any node, Low value equal to it’s Disc value anyway (A node
is ancestor of itself). Then we look into it’s subtree and see if there is any node which can
take us to any of it’s ancestor. If there are multiple back edges in subtree which take us to
different ancestors, then we take the one with minimum Disc value (i.e. the topmost one).
If we look at node F, it has two subtrees. Subtree with node G, takes us to E and C. The
other subtree takes us back to F only. Here topmost ancestor is C where F can reach and
so Low value of F is 3 (The Disc value of C).
Based on above discussion, it should be clear that Low values of B, C, and D are 1 (As A
is the topmost node where B, C and D can reach). In same way, Low values of E, F, G are
3 and Low values of H, I, J are 6.
For any node u, when DFS starts, Low will be set to it’s Disc 1st .
Then later on DFS will be performed on each of it’s children v one by one, Low value of u
can change it two case:
Case1 (Tree Edge): If node v is not visited already, then after DFS of v is complete, then
minimum of low[u] and low[v] will be updated to low[u].
low[u] = min(low[u], low[v]);
Case 2 (Back Edge): When child v is already visited, then minimum of low[u] and Disc[v]
will be updated to low[u].
low[u] = min(low[u], disc[v]);
In case two, can we take low[v] instead of disc[v] ?? . Answer is NO. If you can think why
answer is NO, you probably understood the Low and Disc concept.
435
Chapter 49. Tarjan’s Algorithm to find Strongly Connected Components
Same Low and Disc values help to solve other graph problems like articulation point, bridge
and biconnected component.
To track the subtree rooted at head, we can use a stack (keep pushing node while visiting).
When a head node found, pop all nodes from stack till you get head out of stack.
To make sure, we don’t consider cross edges, when we reach a node which is already visited,
we should process the visited node only if it is present in stack, else ignore the node.
Following is implementation of Tarjan’s algorithm to print all SCCs.
C/C++
436
Chapter 49. Tarjan’s Algorithm to find Strongly Connected Components
public:
Graph(int V); // Constructor
void addEdge(int v, int w); // function to add an edge to graph
void SCC(); // prints strongly connected components
};
Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V];
}
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w);
}
// A recursive function that finds and prints strongly connected
// components using DFS traversal
// u --> The vertex to be visited next
// disc[] --> Stores discovery times of visited vertices
// low[] -- >> earliest visited vertex (the vertex with minimum
// discovery time) that can be reached from subtree
// rooted with current vertex
// *st -- >> To store all the connected ancestors (could be part
// of SCC)
// stackMember[] --> bit/index array for faster check whether
// a node is in stack
void Graph::SCCUtil(int u, int disc[], int low[], stack<int> *st,
bool stackMember[])
{
// A static variable is used for simplicity, we can avoid use
// of static variable by passing a pointer.
static int time = 0;
// Initialize discovery time and low value
disc[u] = low[u] = ++time;
st->push(u);
stackMember[u] = true;
// Go through all vertices adjacent to this
list<int>::iterator i;
for (i = adj[u].begin(); i != adj[u].end(); ++i)
{
int v = *i; // v is current adjacent of 'u'
// If v is not visited yet, then recur for it
if (disc[v] == -1)
437
Chapter 49. Tarjan’s Algorithm to find Strongly Connected Components
{
SCCUtil(v, disc, low, st, stackMember);
// Check if the subtree rooted with 'v' has a
// connection to one of the ancestors of 'u'
// Case 1 (per above discussion on Disc and Low value)
low[u] = min(low[u], low[v]);
}
// Update low value of 'u' only of 'v' is still in stack
// (i.e. it's a back edge, not cross edge).
// Case 2 (per above discussion on Disc and Low value)
else if (stackMember[v] == true)
low[u] = min(low[u], disc[v]);
}
// head node found, pop the stack and print an SCC
int w = 0; // To store stack extracted vertices
if (low[u] == disc[u])
{
while (st->top() != u)
{
w = (int) st->top();
cout << w << " ";
stackMember[w] = false;
st->pop();
}
w = (int) st->top();
cout << w << "n";
stackMember[w] = false;
st->pop();
}
}
// The function to do DFS traversal. It uses SCCUtil()
void Graph::SCC()
{
int *disc = new int[V];
int *low = new int[V];
bool *stackMember = new bool[V];
stack<int> *st = new stack<int>();
// Initialize disc and low, and stackMember arrays
for (int i = 0; i < V; i++)
{
disc[i] = NIL;
low[i] = NIL;
stackMember[i] = false;
438
Chapter 49. Tarjan’s Algorithm to find Strongly Connected Components
}
// Call the recursive helper function to find strongly
// connected components in DFS tree with vertex 'i'
for (int i = 0; i < V; i++)
if (disc[i] == NIL)
SCCUtil(i, disc, low, st, stackMember);
}
// Driver program to test above function
int main()
{
cout << "nSCCs in first graph n";
Graph g1(5);
g1.addEdge(1, 0);
g1.addEdge(0, 2);
g1.addEdge(2, 1);
g1.addEdge(0, 3);
g1.addEdge(3, 4);
g1.SCC();
cout << "nSCCs in second graph n";
Graph g2(4);
g2.addEdge(0, 1);
g2.addEdge(1, 2);
g2.addEdge(2, 3);
g2.SCC();
cout << "nSCCs in third graph n";
Graph g3(7);
g3.addEdge(0, 1);
g3.addEdge(1, 2);
g3.addEdge(2, 0);
g3.addEdge(1, 3);
g3.addEdge(1, 4);
g3.addEdge(1, 6);
g3.addEdge(3, 5);
g3.addEdge(4, 5);
g3.SCC();
cout << "nSCCs in fourth graph n";
Graph g4(11);
g4.addEdge(0,1);g4.addEdge(0,3);
g4.addEdge(1,2);g4.addEdge(1,4);
g4.addEdge(2,0);g4.addEdge(2,6);
g4.addEdge(3,2);
g4.addEdge(4,5);g4.addEdge(4,6);
g4.addEdge(5,6);g4.addEdge(5,7);g4.addEdge(5,8);g4.addEdge(5,9);
439
Chapter 49. Tarjan’s Algorithm to find Strongly Connected Components
g4.addEdge(6,4);
g4.addEdge(7,9);
g4.addEdge(8,9);
g4.addEdge(9,8);
g4.SCC();
cout << "nSCCs in fifth graph n";
Graph g5(5);
g5.addEdge(0,1);
g5.addEdge(1,2);
g5.addEdge(2,3);
g5.addEdge(2,4);
g5.addEdge(3,0);
g5.addEdge(4,2);
g5.SCC();
return 0;
}
Python
440
Chapter 49. Tarjan’s Algorithm to find Strongly Connected Components
441
Chapter 49. Tarjan’s Algorithm to find Strongly Connected Components
#The function to do DFS traversal.
# It uses recursive SCCUtil()
def SCC(self):
# Mark all the vertices as not visited
# and Initialize parent and visited,
# and ap(articulation point) arrays
disc = [-1] * (self.V)
low = [-1] * (self.V)
stackMember = [False] * (self.V)
st =[]
# Call the recursive helper function
# to find articulation points
# in DFS tree rooted with vertex 'i'
for i in range(self.V):
if disc[i] == -1:
self.SCCUtil(i, low, disc, stackMember, st)
# Create a graph given in the above diagram
g1 = Graph(5)
g1.addEdge(1, 0)
g1.addEdge(0, 2)
g1.addEdge(2, 1)
g1.addEdge(0, 3)
g1.addEdge(3, 4)
print "SSC in first graph "
g1.SCC()
g2 = Graph(4)
g2.addEdge(0, 1)
g2.addEdge(1, 2)
g2.addEdge(2, 3)
print "nSSC in second graph "
g2.SCC()
g3 = Graph(7)
g3.addEdge(0, 1)
g3.addEdge(1, 2)
g3.addEdge(2, 0)
442
Chapter 49. Tarjan’s Algorithm to find Strongly Connected Components
g3.addEdge(1, 3)
g3.addEdge(1, 4)
g3.addEdge(1, 6)
g3.addEdge(3, 5)
g3.addEdge(4, 5)
print "nSSC in third graph "
g3.SCC()
g4 = Graph(11)
g4.addEdge(0, 1)
g4.addEdge(0, 3)
g4.addEdge(1, 2)
g4.addEdge(1, 4)
g4.addEdge(2, 0)
g4.addEdge(2, 6)
g4.addEdge(3, 2)
g4.addEdge(4, 5)
g4.addEdge(4, 6)
g4.addEdge(5, 6)
g4.addEdge(5, 7)
g4.addEdge(5, 8)
g4.addEdge(5, 9)
g4.addEdge(6, 4)
g4.addEdge(7, 9)
g4.addEdge(8, 9)
g4.addEdge(9, 8)
print "nSSC in fourth graph "
g4.SCC();
g5 = Graph (5)
g5.addEdge(0, 1)
g5.addEdge(1, 2)
g5.addEdge(2, 3)
g5.addEdge(2, 4)
g5.addEdge(3, 0)
g5.addEdge(4, 2)
print "nSSC in fifth graph "
g5.SCC();
#This code is contributed by Neelam Yadav
Output:
443
Chapter 49. Tarjan’s Algorithm to find Strongly Connected Components
1 2 0
Time Complexity: The above algorithm mainly calls DFS, DFS takes O(V+E) for a
graph represented using adjacency list.
References:
http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm
http://www.ics.uci.edu/~eppstein/161/960220.html#sca
This article is contributed by Anurag Singh. Please write comments if you find anything
incorrect, or you want to share more information about the topic discussed above
Source
https://www.geeksforgeeks.org/tarjan-algorithm-find-strongly-connected-components/
444
Chapter 50
The graph is given in the form of adjacency matrix say ‘graph[V][V]’ where graph[i][j] is 1
if there is an edge from vertex i to vertex j or i is equal to j, otherwise graph[i][j] is 0.
Floyd Warshall Algorithm can be used, we can calculate the distance matrix dist[V][V] using
Floyd Warshall, if dist[i][j] is infinite, then j is not reachable from i, otherwise j is reachable
and value of dist[i][j] will be less than V.
Instead of directly using Floyd Warshall, we can optimize it in terms of space and time, for
this particular problem. Following are the optimizations:
1) Instead of integer resultant matrix (dist[V][V] in floyd warshall), we can create a boolean
reach-ability matrix reach[V][V] (we save space). The value reach[i][j] will be 1 if j is reach-
able from i, otherwise 0.
2) Instead of using arithmetic operations, we can use logical operations. For arithmetic
operation ‘+’, logical and ‘&&’ is used, and for min, logical or ‘’ is used. (We save time by
a constant factor. Time complexity is same though)
C++
445
Chapter 50. Transitive closure of a graph
446
Chapter 50. Transitive closure of a graph
}
/* A utility function to print solution */
void printSolution(int reach[][V])
{
printf ("Following matrix is transitive closure of the given graph\n");
for (int i = 0; i < V; i++)
{
for (int j = 0; j < V; j++)
printf ("%d ", reach[i][j]);
printf("\n");
}
}
// driver program to test above function
int main()
{
/* Let us create the following weighted graph
10
(0)------->(3)
| /|\
5 | |
| | 1
\|/ |
(1)------->(2)
3 */
int graph[V][V] = { {1, 1, 0, 1},
{0, 1, 1, 0},
{0, 0, 1, 1},
{0, 0, 0, 1}
};
// Print the solution
transitiveClosure(graph);
return 0;
}
Java
447
Chapter 50. Transitive closure of a graph
448
Chapter 50. Transitive closure of a graph
449
Chapter 50. Transitive closure of a graph
Python
450
Chapter 50. Transitive closure of a graph
Output:
Source
https://www.geeksforgeeks.org/transitive-closure-of-a-graph/
451
Chapter 51
This is a variation of the standard problem: “Counting the number of connected components
in an undirected graph”.
Before we go to the problem, let us understand what is a connected component. A connected
component of an undirected graph is a subgraph in which every two vertices are connected
to each other by a path(s), and which is connected to no other vertices outside the subgraph.
For example, the graph shown below has three connected components.
452
Chapter 51. Find the number of islands
A graph where all vertices are connected with each other has exactly one connected com-
ponent, consisting of the whole graph. Such graph with only one connected component is
called as Strongly Connected Graph.
The problem can be easily solved by applying DFS() on each component. In each DFS() call,
a component or a sub-graph is visited. We will call DFS on the next un-visited component.
The number of calls to DFS() gives the number of connected components. BFS can also be
used.
What is an island?
A group of connected 1s forms an island. For example, the below matrix contains 5 islands
{1, 1, 0, 0, 0},
{0, 1, 0, 0, 1},
{1, 0, 0, 1, 1},
{0, 0, 0, 0, 0},
{1, 0, 1, 0, 1}
A cell in 2D matrix can be connected to 8 neighbours. So, unlike standard DFS(), where we
recursively call for all adjacent vertices, here we can recursively call for 8 neighbours only.
We keep track of the visited 1s so that they are not visited again.
C/C++
453
Chapter 51. Find the number of islands
#define ROW 5
#define COL 5
// A function to check if a given cell (row, col) can be included in DFS
int isSafe(int M[][COL], int row, int col, bool visited[][COL])
{
// row number is in range, column number is in range and value is 1
// and not yet visited
return (row >= 0) && (row < ROW) &&
(col >= 0) && (col < COL) &&
(M[row][col] && !visited[row][col]);
}
// A utility function to do DFS for a 2D boolean matrix. It only considers
// the 8 neighbours as adjacent vertices
void DFS(int M[][COL], int row, int col, bool visited[][COL])
{
// These arrays are used to get row and column numbers of 8 neighbours
// of a given cell
static int rowNbr[] = {-1, -1, -1, 0, 0, 1, 1, 1};
static int colNbr[] = {-1, 0, 1, -1, 1, -1, 0, 1};
// Mark this cell as visited
visited[row][col] = true;
// Recur for all connected neighbours
for (int k = 0; k < 8; ++k)
if (isSafe(M, row + rowNbr[k], col + colNbr[k], visited) )
DFS(M, row + rowNbr[k], col + colNbr[k], visited);
}
// The main function that returns count of islands in a given boolean
// 2D matrix
int countIslands(int M[][COL])
{
// Make a bool array to mark visited cells.
// Initially all cells are unvisited
bool visited[ROW][COL];
memset(visited, 0, sizeof(visited));
// Initialize count as 0 and travese through the all cells of
// given matrix
int count = 0;
for (int i = 0; i < ROW; ++i)
for (int j = 0; j < COL; ++j)
if (M[i][j] && !visited[i][j]) // If a cell with value 1 is not
{ // visited yet, then new island found
454
Chapter 51. Find the number of islands
Java
455
Chapter 51. Find the number of islands
456
Chapter 51. Find the number of islands
{1, 0, 1, 0, 1}
};
Islands I = new Islands();
System.out.println("Number of islands is: "+ I.countIslands(M));
}
} //Contributed by Aakash Hasija
Python
457
Chapter 51. Find the number of islands
C#
// C# program to count
// islands in boolean
// 2D matrix
using System;
458
Chapter 51. Find the number of islands
class GFG
{
// No of rows
// and columns
static int ROW = 5, COL = 5;
// A function to check if
// a given cell (row, col)
// can be included in DFS
static bool isSafe(int [,]M, int row,
int col, bool [,]visited)
{
// row number is in range,
// column number is in range
// and value is 1 and not
// yet visited
return (row >= 0) && (row < ROW) &&
(col >= 0) && (col < COL) &&
(M[row, col] == 1 &&
!visited[row, col]);
}
// A utility function to do
// DFS for a 2D boolean matrix.
// It only considers the 8
// neighbors as adjacent vertices
static void DFS(int [,]M, int row,
int col, bool [,]visited)
{
// These arrays are used to
// get row and column numbers
// of 8 neighbors of a given cell
int []rowNbr = new int[] {-1, -1, -1, 0,
0, 1, 1, 1};
int []colNbr = new int[] {-1, 0, 1, -1,
1, -1, 0, 1};
// Mark this cell
// as visited
visited[row, col] = true;
// Recur for all
// connected neighbours
for (int k = 0; k < 8; ++k)
if (isSafe(M, row + rowNbr[k], col +
colNbr[k], visited))
DFS(M, row + rowNbr[k],
459
Chapter 51. Find the number of islands
460
Chapter 51. Find the number of islands
PHP
<?php
// Program to count islands
// in boolean 2D matrix
$ROW = 5;
$COL = 5;
// A function to check if a
// given cell (row, col) can
// be included in DFS
function isSafe(&$M, $row, $col,
&$visited)
{
global $ROW, $COL;
// row number is in range,
// column number is in
// range and value is 1
// and not yet visited
return ($row >= 0) && ($row < $ROW) &&
($col >= 0) && ($col < $COL) &&
($M[$row][$col] &&
!isset($visited[$row][$col]));
}
// A utility function to do DFS
// for a 2D boolean matrix. It
// only considers the 8 neighbours
// as adjacent vertices
function DFS(&$M, $row, $col,
&$visited)
{
// These arrays are used to
// get row and column numbers
// of 8 neighbours of a given cell
$rowNbr = array(-1, -1, -1, 0,
0, 1, 1, 1);
$colNbr = array(-1, 0, 1, -1,
1, -1, 0, 1);
// Mark this cell as visited
$visited[$row][$col] = true;
461
Chapter 51. Find the number of islands
462
Chapter 51. Find the number of islands
// This code is contributed
// by ChitraNayal
?>
Output:
Source
https://www.geeksforgeeks.org/find-number-of-islands/
463
Chapter 52
Count all possible walks from a source to a destination with exactly k edges - GeeksforGeeks
Given a directed graph and two vertices ‘u’ and ‘v’ in it, count all possible walks from ‘u’
to ‘v’ with exactly k edges on the walk.
The graph is given as adjacency matrix representation where value of graph[i][j] as 1 indicates
that there is an edge from vertex i to vertex j and a value 0 indicates no edge from i to j.
For example consider the following graph. Let source ‘u’ be vertex 0, destination ‘v’ be 3
and k be 2. The output should be 2 as there are two walk from 0 to 3 with exactly 2 edges.
The walks are {0, 2, 3} and {0, 1, 3}
A simple solution is to start from u, go to all adjacent vertices and recur for adjacent
464
Chapter 52. Count all possible walks from a source to a destination with exactly k edges
vertices with k as k-1, source as adjacent vertex and destination as v. Following is the
implementation of this simple solution.
C++
Java
465
Chapter 52. Count all possible walks from a source to a destination with exactly k edges
import java.util.*;
import java.lang.*;
import java.io.*;
class KPaths
{
static final int V = 4; //Number of vertices
// A naive recursive function to count walks from u
// to v with k edges
int countwalks(int graph[][], int u, int v, int k)
{
// Base cases
if (k == 0 && u == v) return 1;
if (k == 1 && graph[u][v] == 1) return 1;
if (k <= 0) return 0;
// Initialize result
int count = 0;
// Go to all adjacents of u and recur
for (int i = 0; i < V; i++)
if (graph[u][i] == 1) // Check if is adjacent of u
count += countwalks(graph, i, v, k-1);
return count;
}
// Driver method
public static void main (String[] args) throws java.lang.Exception
{
/* Let us create the graph shown in above diagram*/
int graph[][] =new int[][] { {0, 1, 1, 1},
{0, 0, 0, 1},
{0, 0, 0, 1},
{0, 0, 0, 0}
};
int u = 0, v = 3, k = 2;
KPaths p = new KPaths();
System.out.println(p.countwalks(graph, u, v, k));
}
}//Contributed by Aakash Hasija
Python3
466
Chapter 52. Count all possible walks from a source to a destination with exactly k edges
C#
467
Chapter 52. Count all possible walks from a source to a destination with exactly k edges
468
Chapter 52. Count all possible walks from a source to a destination with exactly k edges
}
}
// This code is contributed by nitin mittal.
PHP
<?php
// PHP program to count walks from u
// to v with exactly k edges
// Number of vertices in the graph
$V = 4;
// A naive recursive function to count
// walks from u to v with k edges
function countwalks( $graph, $u, $v, $k)
{
global $V;
// Base cases
if ($k == 0 and $u == $v)
return 1;
if ($k == 1 and $graph[$u][$v])
return 1;
if ($k <= 0)
return 0;
// Initialize result
$count = 0;
// Go to all adjacents of u and recur
for ( $i = 0; $i < $V; $i++)
// Check if is adjacent of u
if ($graph[$u][$i] == 1)
$count += countwalks($graph, $i,
$v, $k - 1);
return $count;
}
// Driver Code
/* Let us create the graph
shown in above diagram*/
$graph = array(array(0, 1, 1, 1),
array(0, 0, 0, 1),
array(0, 0, 0, 1),
469
Chapter 52. Count all possible walks from a source to a destination with exactly k edges
array(0, 0, 0, 0));
$u = 0; $v = 3; $k = 2;
echo countwalks($graph, $u, $v, $k);
// This code is contributed by anuj_67.
?>
Output:
The worst case time complexity of the above function is O(Vk ) where V is the number of
vertices in the given graph. We can simply analyze the time complexity by drawing recursion
tree. The worst occurs for a complete graph. In worst case, every internal node of recursion
tree would have exactly n children.
We can optimize the above solution using Dynamic Programming. The idea is to build
a 3D table where first dimension is source, second dimension is destination, third dimension
is number of edges from source to destination, and the value is count of walks. Like other
Dynamic Programming problems, we fill the 3D table in bottom up manner.
C++
470
Chapter 52. Count all possible walks from a source to a destination with exactly k edges
if (e == 0 && i == j)
count[i][j][e] = 1;
if (e == 1 && graph[i][j])
count[i][j][e] = 1;
// go to adjacent only when number of edges is more than 1
if (e > 1)
{
for (int a = 0; a < V; a++) // adjacent of source i
if (graph[i][a])
count[i][j][e] += count[a][j][e-1];
}
}
}
}
return count[u][v][k];
}
// driver program to test above function
int main()
{
/* Let us create the graph shown in above diagram*/
int graph[V][V] = { {0, 1, 1, 1},
{0, 0, 0, 1},
{0, 0, 0, 1},
{0, 0, 0, 0}
};
int u = 0, v = 3, k = 2;
cout << countwalks(graph, u, v, k);
return 0;
}
Java
471
Chapter 52. Count all possible walks from a source to a destination with exactly k edges
472
Chapter 52. Count all possible walks from a source to a destination with exactly k edges
C#
473
Chapter 52. Count all possible walks from a source to a destination with exactly k edges
count[i,j,e] +=
count[a,j,e-1];
}
}
}
}
return count[u,v,k];
}
// Driver method
public static void Main ()
{
/* Let us create the graph shown in
above diagram*/
int [,]graph = { {0, 1, 1, 1},
{0, 0, 0, 1},
{0, 0, 0, 1},
{0, 0, 0, 0} };
int u = 0, v = 3, k = 2;
Console.WriteLine(
countwalks(graph, u, v, k));
}
}
// This is Code Contributed by anuj_67.
Output:
Time complexity of the above DP based solution is O(V3 K) which is much better than the
naive solution.
We can also use Divide and Conquer to solve the above problem in O(V3 Logk) time.
The count of walks of length k from u to v is the [u][v]’th entry in (graph[V][V])k . We
can calculate power of by doing O(Logk) multiplication by using the divide and conquer
technique to calculate power. A multiplication between two matrices of size V x V takes
O(V3 ) time. Therefore overall time complexity of this method is O(V3 Logk).
Improved By : nitin mittal, vt_m
Source
https://www.geeksforgeeks.org/count-possible-paths-source-destination-exactly-k-edges/
474
Chapter 53
475
Chapter 53. Euler Circuit in a Directed Graph
476
Chapter 53. Euler Circuit in a Directed Graph
// Check if in degree and out degree of every vertex is same
for (int i = 0; i < V; i++)
if (adj[i].size() != in[i])
return false;
return true;
}
// A recursive function to do DFS starting from v
void Graph::DFSUtil(int v, bool visited[])
{
// Mark the current node as visited and print it
visited[v] = true;
// Recur for all the vertices adjacent to this vertex
list<int>::iterator i;
for (i = adj[v].begin(); i != adj[v].end(); ++i)
if (!visited[*i])
DFSUtil(*i, visited);
}
// Function that returns reverse (or transpose) of this graph
// This function is needed in isSC()
Graph Graph::getTranspose()
{
Graph g(V);
for (int v = 0; v < V; v++)
{
// Recur for all the vertices adjacent to this vertex
list<int>::iterator i;
for(i = adj[v].begin(); i != adj[v].end(); ++i)
{
g.adj[*i].push_back(v);
(g.in[v])++;
}
}
return g;
}
// This function returns true if all non-zero degree vertices of
// graph are strongly connected (Please refer
// https://www.geeksforgeeks.org/connectivity-in-a-directed-graph/ )
bool Graph::isSC()
{
// Mark all the vertices as not visited (For first DFS)
bool visited[V];
for (int i = 0; i < V; i++)
477
Chapter 53. Euler Circuit in a Directed Graph
visited[i] = false;
// Find the first vertex with non-zero degree
int n;
for (n = 0; n < V; n++)
if (adj[n].size() > 0)
break;
// Do DFS traversal starting from first non zero degree vertex.
DFSUtil(n, visited);
// If DFS traversal doesn't visit all vertices, then return false.
for (int i = 0; i < V; i++)
if (adj[i].size() > 0 && visited[i] == false)
return false;
// Create a reversed graph
Graph gr = getTranspose();
// Mark all the vertices as not visited (For second DFS)
for (int i = 0; i < V; i++)
visited[i] = false;
// Do DFS for reversed graph starting from first vertex.
// Staring Vertex must be same starting point of first DFS
gr.DFSUtil(n, visited);
// If all vertices are not visited in second DFS, then
// return false
for (int i = 0; i < V; i++)
if (adj[i].size() > 0 && visited[i] == false)
return false;
return true;
}
// Driver program to test above functions
int main()
{
// Create a graph given in the above diagram
Graph g(5);
g.addEdge(1, 0);
g.addEdge(0, 2);
g.addEdge(2, 1);
g.addEdge(0, 3);
g.addEdge(3, 4);
g.addEdge(4, 0);
478
Chapter 53. Euler Circuit in a Directed Graph
if (g.isEulerianCycle())
cout << "Given directed graph is eulerian n";
else
cout << "Given directed graph is NOT eulerian n";
return 0;
}
Java
479
Chapter 53. Euler Circuit in a Directed Graph
int n;
// Recur for all the vertices adjacent to this vertex
Iterator<Integer> i =adj[v].iterator();
while (i.hasNext())
{
n = i.next();
if (!visited[n])
DFSUtil(n,visited);
}
}
// Function that returns reverse (or transpose) of this graph
Graph getTranspose()
{
Graph g = new Graph(V);
for (int v = 0; v < V; v++)
{
// Recur for all the vertices adjacent to this vertex
Iterator<Integer> i = adj[v].listIterator();
while (i.hasNext())
{
g.adj[i.next()].add(v);
(g.in[v])++;
}
}
return g;
}
// The main function that returns true if graph is strongly
// connected
Boolean isSC()
{
// Step 1: Mark all the vertices as not visited (For
// first DFS)
Boolean visited[] = new Boolean[V];
for (int i = 0; i < V; i++)
visited[i] = false;
// Step 2: Do DFS traversal starting from first vertex.
DFSUtil(0, visited);
// If DFS traversal doesn't visit all vertices, then return false.
for (int i = 0; i < V; i++)
if (visited[i] == false)
return false;
480
Chapter 53. Euler Circuit in a Directed Graph
481
Chapter 53. Euler Circuit in a Directed Graph
else
System.out.println("Given directed graph is NOT eulerian ");
}
}
//This code is contributed by Aakash Hasija
Python
482
Chapter 53. Euler Circuit in a Directed Graph
self.DFSUtil(v, visited)
# If DFS traversal doesn't visit all
# vertices, then return false.
for i in range(self.V):
if visited[i] == False:
return False
gr = self.getTranspose()
visited = [False] * self.V
gr.DFSUtil(v, visited)
for i in range(self.V):
if visited[i] == False:
return False
return True
def isEulerianCycle(self):
# Check if all non-zero degree vertices
# are connected
if self.isSC() == False:
return False
# Check if in degree and out degree of
# every vertex is same
for v in range(self.V):
if len(self.graph[v]) != self.IN[v]:
return False
return True
g = Graph(5);
g.addEdge(1, 0);
g.addEdge(0, 2);
g.addEdge(2, 1);
g.addEdge(0, 3);
g.addEdge(3, 4);
g.addEdge(4, 0);
if g.isEulerianCycle():
print "Given directed graph is eulerian";
else:
print "Given directed graph is NOT eulerian";
# This code is contributed by Divyanshu Mehta
483
Chapter 53. Euler Circuit in a Directed Graph
Output:
Source
https://www.geeksforgeeks.org/euler-circuit-directed-graph/
484
Chapter 54
Biconnected Components
• 8–9
• 8–5 7–8 5–7
• 6–0 5–6 1–5 0–1
485
Chapter 54. Biconnected Components
• 10–11
Algorithm is based on Disc and Low Values discussed in Strongly Connected Components
Article.
Idea is to store visited edges in a stack while DFS on a graph and keep looking for Artic-
ulation Points (highlighted in above figure). As soon as an Articulation Point u is found,
all edges visited while DFS from node u onwards will form one biconnected component.
When DFS completes for one connected component, all edges present in stack will form a
biconnected component.
If there is no Articulation Point in graph, then graph is biconnected and so there will be
one biconnected component which is the graph itself.
C++
486
Chapter 54. Biconnected Components
Graph::Graph(int V)
{
this->V = V;
this->E = 0;
adj = new list<int>[V];
}
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w);
E++;
}
// A recursive function that finds and prints strongly connected
// components using DFS traversal
// u --> The vertex to be visited next
// disc[] --> Stores discovery times of visited vertices
// low[] -- >> earliest visited vertex (the vertex with minimum
// discovery time) that can be reached from subtree
// rooted with current vertex
// *st -- >> To store visited edges
void Graph::BCCUtil(int u, int disc[], int low[], list<Edge>* st,
int parent[])
{
// A static variable is used for simplicity, we can avoid use
// of static variable by passing a pointer.
static int time = 0;
// Initialize discovery time and low value
disc[u] = low[u] = ++time;
int children = 0;
// Go through all vertices adjacent to this
list<int>::iterator i;
for (i = adj[u].begin(); i != adj[u].end(); ++i) {
int v = *i; // v is current adjacent of 'u'
// If v is not visited yet, then recur for it
if (disc[v] == -1) {
children++;
parent[v] = u;
// store the edge in stack
st->push_back(Edge(u, v));
BCCUtil(v, disc, low, st, parent);
// Check if the subtree rooted with 'v' has a
// connection to one of the ancestors of 'u'
487
Chapter 54. Biconnected Components
488
Chapter 54. Biconnected Components
int j = 0;
// If stack is not empty, pop all edges from stack
while (st->size() > 0) {
j = 1;
cout << st->back().u << "--" << st->back().v << " ";
st->pop_back();
}
if (j == 1) {
cout << endl;
count++;
}
}
}
// Driver program to test above function
int main()
{
Graph g(12);
g.addEdge(0, 1);
g.addEdge(1, 0);
g.addEdge(1, 2);
g.addEdge(2, 1);
g.addEdge(1, 3);
g.addEdge(3, 1);
g.addEdge(2, 3);
g.addEdge(3, 2);
g.addEdge(2, 4);
g.addEdge(4, 2);
g.addEdge(3, 4);
g.addEdge(4, 3);
g.addEdge(1, 5);
g.addEdge(5, 1);
g.addEdge(0, 6);
g.addEdge(6, 0);
g.addEdge(5, 6);
g.addEdge(6, 5);
g.addEdge(5, 7);
g.addEdge(7, 5);
g.addEdge(5, 8);
g.addEdge(8, 5);
g.addEdge(7, 8);
g.addEdge(8, 7);
g.addEdge(8, 9);
g.addEdge(9, 8);
g.addEdge(10, 11);
g.addEdge(11, 10);
g.BCC();
cout << "Above are " << count << " biconnected components in graph";
489
Chapter 54. Biconnected Components
return 0;
}
Java
490
Chapter 54. Biconnected Components
491
Chapter 54. Biconnected Components
// Update low value of 'u' only of 'v' is still in stack
// (i.e. it's a back edge, not cross edge).
// Case 2 -- per Strongly Connected Components Article
else if (v != parent[u] && disc[v] < low[u]) {
if (low[u] > disc[v])
low[u] = disc[v];
st.add(new Edge(u, v));
}
}
}
// The function to do DFS traversal. It uses BCCUtil()
void BCC()
{
int disc[] = new int[V];
int low[] = new int[V];
int parent[] = new int[V];
LinkedList<Edge> st = new LinkedList<Edge>();
// Initialize disc and low, and parent arrays
for (int i = 0; i < V; i++) {
disc[i] = -1;
low[i] = -1;
parent[i] = -1;
}
for (int i = 0; i < V; i++) {
if (disc[i] == -1)
BCCUtil(i, disc, low, st, parent);
int j = 0;
// If stack is not empty, pop all edges from stack
while (st.size() > 0) {
j = 1;
System.out.print(st.getLast().u + "--" + st.getLast().v + " ");
st.removeLast();
}
if (j == 1) {
System.out.println();
count++;
}
}
}
public static void main(String args[])
{
492
Chapter 54. Biconnected Components
Python
493
Chapter 54. Biconnected Components
class Graph:
def __init__(self, vertices):
# No. of vertices
self.V = vertices
# default dictionary to store graph
self.graph = defaultdict(list)
# time is used to find discovery times
self.Time = 0
# Count is number of biconnected components
self.count = 0
# function to add an edge to graph
def addEdge(self, u, v):
self.graph[u].append(v)
self.graph[v].append(u)
'''A recursive function that finds and prints strongly connected
components using DFS traversal
u --> The vertex to be visited next
disc[] --> Stores discovery times of visited vertices
low[] -- >> earliest visited vertex (the vertex with minimum
discovery time) that can be reached from subtree
rooted with current vertex
st -- >> To store visited edges'''
def BCCUtil(self, u, parent, low, disc, st):
# Count of children in current node
children = 0
# Initialize discovery time and low value
disc[u] = self.Time
low[u] = self.Time
self.Time += 1
# Recur for all the vertices adjacent to this vertex
for v in self.graph[u]:
# If v is not visited yet, then make it a child of u
# in DFS tree and recur for it
if disc[v] == -1 :
parent[v] = u
children += 1
st.append((u, v)) # store the edge in stack
self.BCCUtil(v, parent, low, disc, st)
494
Chapter 54. Biconnected Components
# Check if the subtree rooted with v has a connection to
# one of the ancestors of u
# Case 1 -- per Strongly Connected Components Article
low[u] = min(low[u], low[v])
# If u is an articulation point, pop
# all edges from stack till (u, v)
if parent[u] == -1 and children > 1 or parent[u] != -1 and low[v] >= disc[u]:
self.count += 1 # increment count
w = -1
while w != (u, v):
w = st.pop()
print w,
print""
elif v != parent[u] and low[u] > disc[v]:
'''Update low value of 'u' only of 'v' is still in stack
(i.e. it's a back edge, not cross edge).
Case 2
-- per Strongly Connected Components Article'''
low[u] = min(low [u], disc[v])
st.append((u, v))
# The function to do DFS traversal.
# It uses recursive BCCUtil()
def BCC(self):
# Initialize disc and low, and parent arrays
disc = [-1] * (self.V)
low = [-1] * (self.V)
parent = [-1] * (self.V)
st = []
# Call the recursive helper function to
# find articulation points
# in DFS tree rooted with vertex 'i'
for i in range(self.V):
if disc[i] == -1:
self.BCCUtil(i, parent, low, disc, st)
# If stack is not empty, pop all edges from stack
if st:
self.count = self.count + 1
495
Chapter 54. Biconnected Components
while st:
w = st.pop()
print w,
print ""
# Create a graph given in the above diagram
g = Graph(12)
g.addEdge(0, 1)
g.addEdge(1, 2)
g.addEdge(1, 3)
g.addEdge(2, 3)
g.addEdge(2, 4)
g.addEdge(3, 4)
g.addEdge(1, 5)
g.addEdge(0, 6)
g.addEdge(5, 6)
g.addEdge(5, 7)
g.addEdge(5, 8)
g.addEdge(7, 8)
g.addEdge(8, 9)
g.addEdge(10, 11)
g.BCC();
print ("Above are % d biconnected components in graph" %(g.count));
# This code is contributed by Neelam Yadav
Output:
This article is contributed by Anurag Singh. Please write comments if you find anything
incorrect, or you want to share more information about the topic discussed above
Improved By : VismayMalondkar
Source
https://www.geeksforgeeks.org/biconnected-components/
496
Chapter 55
497
Chapter 55. Graph Coloring (Introduction and Applications)
Source
https://www.geeksforgeeks.org/graph-coloring-applications/
498
Chapter 56
Following are C++ and Java implementations of the above Greedy Algorithm.
C++
499
Chapter 56. Greedy Algorithm for Graph Coloring
{
int V; // No. of vertices
list<int> *adj; // A dynamic array of adjacency lists
public:
// Constructor and destructor
Graph(int V) { this->V = V; adj = new list<int>[V]; }
~Graph() { delete [] adj; }
// function to add an edge to graph
void addEdge(int v, int w);
// Prints greedy coloring of the vertices
void greedyColoring();
};
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w);
adj[w].push_back(v); // Note: the graph is undirected
}
// Assigns colors (starting from 0) to all vertices and prints
// the assignment of colors
void Graph::greedyColoring()
{
int result[V];
// Assign the first color to first vertex
result[0] = 0;
// Initialize remaining V-1 vertices as unassigned
for (int u = 1; u < V; u++)
result[u] = -1; // no color is assigned to u
// A temporary array to store the available colors. True
// value of available[cr] would mean that the color cr is
// assigned to one of its adjacent vertices
bool available[V];
for (int cr = 0; cr < V; cr++)
available[cr] = false;
// Assign colors to remaining V-1 vertices
for (int u = 1; u < V; u++)
{
// Process all adjacent vertices and flag their colors
// as unavailable
list<int>::iterator i;
for (i = adj[u].begin(); i != adj[u].end(); ++i)
500
Chapter 56. Greedy Algorithm for Graph Coloring
501
Chapter 56. Greedy Algorithm for Graph Coloring
Java
502
Chapter 56. Greedy Algorithm for Graph Coloring
// Assign colors to remaining V-1 vertices
for (int u = 1; u < V; u++)
{
// Process all adjacent vertices and flag their colors
// as unavailable
Iterator<Integer> it = adj[u].iterator() ;
while (it.hasNext())
{
int i = it.next();
if (result[i] != -1)
available[result[i]] = false;
}
// Find the first available color
int cr;
for (cr = 0; cr < V; cr++){
if (available[cr])
break;
}
result[u] = cr; // Assign the found color
// Reset the values back to true for the next iteration
Arrays.fill(available, true);
}
// print the result
for (int u = 0; u < V; u++)
System.out.println("Vertex " + u + " ---> Color "
+ result[u]);
}
// Driver method
public static void main(String args[])
{
Graph g1 = new Graph(5);
g1.addEdge(0, 1);
g1.addEdge(0, 2);
g1.addEdge(1, 2);
g1.addEdge(1, 3);
g1.addEdge(2, 3);
g1.addEdge(3, 4);
System.out.println("Coloring of graph 1");
g1.greedyColoring();
System.out.println();
Graph g2 = new Graph(5);
503
Chapter 56. Greedy Algorithm for Graph Coloring
g2.addEdge(0, 1);
g2.addEdge(0, 2);
g2.addEdge(1, 2);
g2.addEdge(1, 4);
g2.addEdge(2, 4);
g2.addEdge(4, 3);
System.out.println("Coloring of graph 2 ");
g2.greedyColoring();
}
}
// This code is contributed by Aakash Hasija
Output:
Coloring of graph 1
Vertex 0 ---> Color 0
Vertex 1 ---> Color 1
Vertex 2 ---> Color 2
Vertex 3 ---> Color 0
Vertex 4 ---> Color 1
Coloring of graph 2
Vertex 0 ---> Color 0
Vertex 1 ---> Color 1
Vertex 2 ---> Color 2
Vertex 3 ---> Color 0
Vertex 4 ---> Color 3
504
Chapter 56. Greedy Algorithm for Graph Coloring
So the order in which the vertices are picked is important. Many people have sug-
gested different ways to find an ordering that work better than the basic algorithm
on average. The most common is Welsh–Powell Algorithm which considers vertices in
descending order of degrees.
How does the basic algorithm guarantee an upper bound of d+1?
Here d is the maximum degree in the given graph. Since d is maximum degree, a vertex
cannot be attached to more than d vertices. When we color a vertex, at most d colors could
have already been used by its adjacent. To color this vertex, we need to pick the smallest
numbered color that is not used by the adjacent vertices. If colors are numbered like 1, 2,
…., then the value of such smallest number must be between 1 to d+1 (Note that d numbers
are already picked by adjacent vertices).
505
Chapter 56. Greedy Algorithm for Graph Coloring
This can also be proved using induction. See thisvideo lecture for proof.
We will soon be discussing some interesting facts about chromatic number and graph color-
ing.
Improved By : ChamanJhinga
Source
https://www.geeksforgeeks.org/graph-coloring-set-2-greedy-algorithm/
506
Chapter 57
For example, consider the graph shown in figure on right side. A TSP tour in the graph is
1-2-4-3-1. The cost of the tour is 10+25+30+15 which is 80.
The problem is a famous NP hardproblem. There is no polynomial time know solution for
this problem.
Following are different solutions for the traveling salesman problem.
507
Chapter 57. Travelling Salesman Problem (Naive and Dynamic Programming)
Naive Solution:
1) Consider city 1 as the starting and ending point.
2) Generate all (n-1)! Permutationsof cities.
3) Calculate cost of every permutation and keep track of minimum cost permutation.
4) Return the permutation with minimum cost.
Time Complexity: Θ(n!)
Dynamic Programming:
Let the given set of vertices be {1, 2, 3, 4,….n}. Let us consider 1 as starting and ending
point of output. For every other vertex i (other than 1), we find the minimum cost path
with 1 as the starting point, i as the ending point and all vertices appearing exactly once.
Let the cost of this path be cost(i), the cost of corresponding Cycle would be cost(i) + dist(i,
1) where dist(i, 1) is the distance from i to 1. Finally, we return the minimum of all [cost(i)
+ dist(i, 1)] values. This looks simple so far. Now the question is how to get cost(i)?
To calculate cost(i) using Dynamic Programming, we need to have some recursive relation
in terms of sub-problems. Let us define a term C(S, i) be the cost of the minimum cost path
visiting each vertex in set S exactly once, starting at 1 and ending at i.
We start with all subsets of size 2 and calculate C(S, i) for all subsets where S is the subset,
then we calculate C(S, i) for all subsets S of size 3 and so on. Note that 1 must be present
in every subset.
For a set of size n, we consider n-2 subsets each of size n-1 such that all subsets don’t have
nth in them.
Using the above recurrence relation, we can write dynamic programming based solution.
There are at most O(n*2n ) subproblems, and each one takes linear time to solve. The total
running time is therefore O(n2 *2n ). The time complexity is much less than O(n!), but still
exponential. Space required is also exponential. So this approach is also infeasible even for
slightly higher number of vertices.
We will soon be discussing approximate algorithms for travelling salesman problem.
Next Article: Traveling Salesman Problem Set 2
References:
http://www.lsi.upc.edu/~mjserna/docencia/algofib/P07/dynprog.pdf
http://www.cs.berkeley.edu/~vazirani/algorithms/chap6.pdf
Source
https://www.geeksforgeeks.org/travelling-salesman-problem-set-1/
508
Chapter 58
509
Chapter 58. Travelling Salesman Problem (Approximate using MST)
In this case, the approximate algorithm produces the optimal tour, but it may not produce
optimal tour in all cases.
How is this algorithm 2-approximate? The cost of the output produced by the above
algorithm is never more than twice the cost of best possible output. Let us see how is this
guaranteed by the above algorithm.
Let us define a term full walk to understand this. A full walk is lists all vertices when they
are first visited in preorder, it also list vertices when they are returned after a subtree is
visited in preorder. The full walk of above tree would be 1-2-1-4-1-3-1.
Following are some important facts that prove the 2-approximateness.
1) The cost of best possible Travelling Salesman tour is never less than the cost of MST.
(The definition of MSTsays, it is a minimum cost tree that connects all vertices).
2) The total cost of full walk is at most twice the cost of MST (Every edge of MST is visited
at-most twice)
3) The output of the above algorithm is less than the cost of full walk. In above algorithm,
we print preorder walk as output. In preorder walk, two or more edges of full walk are
replaced with a single edge. For example, 2-1 and 1-4 are replaced by 1 edge 2-4. So if the
graph follows triangle inequality, then this is always true.
From the above three statements, we can conclude that the cost of output produced by the
approximate algorithm is never more than twice the cost of best possible solution.
We have discussed a very simple 2-approximate algorithm for the travelling salesman
problem. There are other better approximate algorithms for the problem. For example
Christofides algorithm is 1.5 approximate algorithm. We will soon be discussing these
algorithms as separate posts.
References:
Introduction to Algorithms 3rd Edition by Clifford Stein, Thomas H. Cormen, Charles E.
Leiserson, Ronald L. Rivest
http://www.personal.kent.edu/~rmuhamma/Algorithms/MyAlgorithms/AproxAlgor/TSP/tsp.htm
Improved By : PranamLashkari
510
Chapter 58. Travelling Salesman Problem (Approximate using MST)
Source
https://www.geeksforgeeks.org/travelling-salesman-problem-set-2-approximate-using-mst/
511
Chapter 59
Hamiltonian Cycle
(0)--(1)--(2)
| / \ |
| / \ |
| / \ |
(3)-------(4)
(0)--(1)--(2)
| / \ |
512
Chapter 59. Hamiltonian Cycle
| / \ |
| / \ |
(3) (4)
Naive Algorithm
Generate all possible configurations of vertices and print a configuration that satisfies the
given constraints. There will be n! (n factorial) configurations.
Backtracking Algorithm
Create an empty path array and add vertex 0 to it. Add other vertices, starting from the
vertex 1. Before adding a vertex, check for whether it is adjacent to the previously added
vertex and not already added. If we find such a vertex, we add the vertex as part of the
solution. If we do not find a vertex then we return false.
Implementation of Backtracking solution
Following are implementations of the Backtracking solution.
C/C++
513
Chapter 59. Hamiltonian Cycle
514
Chapter 59. Hamiltonian Cycle
}
/* This function solves the Hamiltonian Cycle problem using Backtracking.
It mainly uses hamCycleUtil() to solve the problem. It returns false
if there is no Hamiltonian Cycle possible, otherwise return true and
prints the path. Please note that there may be more than one solutions,
this function prints one of the feasible solutions. */
bool hamCycle(bool graph[V][V])
{
int *path = new int[V];
for (int i = 0; i < V; i++)
path[i] = -1;
/* Let us put vertex 0 as the first vertex in the path. If there is
a Hamiltonian Cycle, then the path can be started from any point
of the cycle as the graph is undirected */
path[0] = 0;
if ( hamCycleUtil(graph, path, 1) == false )
{
printf("\nSolution does not exist");
return false;
}
printSolution(path);
return true;
}
/* A utility function to print solution */
void printSolution(int path[])
{
printf ("Solution Exists:"
" Following is one Hamiltonian Cycle \n");
for (int i = 0; i < V; i++)
printf(" %d ", path[i]);
// Let us print the first vertex again to show the complete cycle
printf(" %d ", path[0]);
printf("\n");
}
// driver program to test above function
int main()
{
/* Let us create the following graph
(0)--(1)--(2)
| / \ |
| / \ |
| / \ |
515
Chapter 59. Hamiltonian Cycle
(3)-------(4) */
bool graph1[V][V] = {{0, 1, 0, 1, 0},
{1, 0, 1, 1, 1},
{0, 1, 0, 0, 1},
{1, 1, 0, 0, 1},
{0, 1, 1, 1, 0},
};
// Print the solution
hamCycle(graph1);
/* Let us create the following graph
(0)--(1)--(2)
| / \ |
| / \ |
| / \ |
(3) (4) */
bool graph2[V][V] = {{0, 1, 0, 1, 0},
{1, 0, 1, 1, 1},
{0, 1, 0, 0, 1},
{1, 1, 0, 0, 0},
{0, 1, 1, 0, 0},
};
// Print the solution
hamCycle(graph2);
return 0;
}
Java
516
Chapter 59. Hamiltonian Cycle
/* Check if the vertex has already been included.
This step can be optimized by creating an array
of size V */
for (int i = 0; i < pos; i++)
if (path[i] == v)
return false;
return true;
}
/* A recursive utility function to solve hamiltonian
cycle problem */
boolean hamCycleUtil(int graph[][], int path[], int pos)
{
/* base case: If all vertices are included in
Hamiltonian Cycle */
if (pos == V)
{
// And if there is an edge from the last included
// vertex to the first vertex
if (graph[path[pos - 1]][path[0]] == 1)
return true;
else
return false;
}
// Try different vertices as a next candidate in
// Hamiltonian Cycle. We don't try for 0 as we
// included 0 as starting point in in hamCycle()
for (int v = 1; v < V; v++)
{
/* Check if this vertex can be added to Hamiltonian
Cycle */
if (isSafe(v, graph, path, pos))
{
path[pos] = v;
/* recur to construct rest of the path */
if (hamCycleUtil(graph, path, pos + 1) == true)
return true;
/* If adding vertex v doesn't lead to a solution,
then remove it */
path[pos] = -1;
}
}
517
Chapter 59. Hamiltonian Cycle
518
Chapter 59. Hamiltonian Cycle
HamiltonianCycle hamiltonian =
new HamiltonianCycle();
/* Let us create the following graph
(0)--(1)--(2)
| / \ |
| / \ |
| / \ |
(3)-------(4) */
int graph1[][] = {{0, 1, 0, 1, 0},
{1, 0, 1, 1, 1},
{0, 1, 0, 0, 1},
{1, 1, 0, 0, 1},
{0, 1, 1, 1, 0},
};
// Print the solution
hamiltonian.hamCycle(graph1);
/* Let us create the following graph
(0)--(1)--(2)
| / \ |
| / \ |
| / \ |
(3) (4) */
int graph2[][] = {{0, 1, 0, 1, 0},
{1, 0, 1, 1, 1},
{0, 1, 0, 0, 1},
{1, 1, 0, 0, 0},
{0, 1, 1, 0, 0},
};
// Print the solution
hamiltonian.hamCycle(graph2);
}
}
// This code is contributed by Abhishek Shankhadhar
Python
519
Chapter 59. Hamiltonian Cycle
520
Chapter 59. Hamiltonian Cycle
def hamCycle(self):
path = [-1] * self.V
''' Let us put vertex 0 as the first vertex
in the path. If there is a Hamiltonian Cycle,
then the path can be started from any point
of the cycle as the graph is undirected '''
path[0] = 0
if self.hamCycleUtil(path,1) == False:
print "Solution does not exist\n"
return False
self.printSolution(path)
return True
def printSolution(self, path):
print "Solution Exists: Following is one Hamiltonian Cycle"
for vertex in path:
print vertex,
print path[0], "\n"
# Driver Code
''' Let us create the following graph
(0)--(1)--(2)
| / \ |
| / \ |
| / \ |
(3)-------(4) '''
g1 = Graph(5)
g1.graph = [ [0, 1, 0, 1, 0], [1, 0, 1, 1, 1],
[0, 1, 0, 0, 1,],[1, 1, 0, 0, 1],
[0, 1, 1, 1, 0], ]
# Print the solution
g1.hamCycle();
''' Let us create the following graph
(0)--(1)--(2)
| / \ |
| / \ |
| / \ |
(3) (4) '''
g2 = Graph(5)
g2.graph = [ [0, 1, 0, 1, 0], [1, 0, 1, 1, 1],
[0, 1, 0, 0, 1,], [1, 1, 0, 0, 0],
[0, 1, 1, 0, 0], ]
521
Chapter 59. Hamiltonian Cycle
# Print the solution
g2.hamCycle();
# This code is contributed by Divyanshu Mehta
Output:
Note that the above code always prints cycle starting from 0. Starting point should not
matter as cycle can be started from any point. If you want to change the starting point,
you should make two changes to above code.
Change “path[0] = 0;” to “path[0] = s;” where s is your new starting point. Also change
loop “for (int v = 1; v < V; v++)” in hamCycleUtil() to ”for (int v = 0; v < V; v++)”.
Please write comments if you find anything incorrect, or you want to share more information
about the topic discussed above.
Source
https://www.geeksforgeeks.org/hamiltonian-cycle-backtracking-6/
522
Chapter 60
Vertex Cover Problem is a known NP Complete problem, i.e., there is no polynomial time
solution for this unless P = NP. There are approximate polynomial time algorithms to solve
the problem though. Following is a simple approximate algorithm adapted from CLRS
book.
Approximate Algorithm for Vertex Cover:
523
Chapter 60. Vertex Cover Problem Set 1 (Introduction and Approximate Algorithm)
4) Return result
524
Chapter 60. Vertex Cover Problem Set 1 (Introduction and Approximate Algorithm)
525
Chapter 60. Vertex Cover Problem Set 1 (Introduction and Approximate Algorithm)
526
Chapter 60. Vertex Cover Problem Set 1 (Introduction and Approximate Algorithm)
{
// An edge is only picked when both visited[u] and visited[v]
// are false
if (visited[u] == false)
{
// Go through all adjacents of u and pick the first not
// yet visited vertex (We are basically picking an edge
// (u, v) from remaining edges.
for (i= adj[u].begin(); i != adj[u].end(); ++i)
{
int v = *i;
if (visited[v] == false)
{
// Add the vertices (u, v) to the result set.
// We make the vertex u and v visited so that
// all edges from/to them would be ignored
visited[v] = true;
visited[u] = true;
break;
}
}
}
}
// Print the vertex cover
for (int i=0; i<V; i++)
if (visited[i])
cout << i << " ";
}
// Driver program to test methods of graph class
int main()
{
// Create a graph given in the above diagram
Graph g(7);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 3);
g.addEdge(3, 4);
g.addEdge(4, 5);
g.addEdge(5, 6);
g.printVertexCover();
return 0;
}
Java
527
Chapter 60. Vertex Cover Problem Set 1 (Introduction and Approximate Algorithm)
528
Chapter 60. Vertex Cover Problem Set 1 (Introduction and Approximate Algorithm)
Output:
0 1 3 4 5 6
529
Chapter 60. Vertex Cover Problem Set 1 (Introduction and Approximate Algorithm)
Exact Algorithms:
Although the problem is NP complete, it can be solved in polynomial time for following
types of graphs.
1) Bipartite Graph
2) Tree Graph
The problem to check whether there is a vertex cover of size smaller than or equal to a given
number k can also be solved in polynomial time if k is bounded by O(LogV) (Refer this)
We will soon be discussing exact algorithms for vertex cover.
This article is contributed by Shubham. Please write comments if you find anything
incorrect, or you want to share more information about the topic discussed above
Source
https://www.geeksforgeeks.org/vertex-cover-problem-set-1-introduction-approximate-algorithm-2/
530
Chapter 61
There is no polynomial time solution available for this problem as the problem is a known
NP-Hard problem. There is a polynomial time Greedy approximate algorithm, the greedy
algorithm provides a solution which is never worse that twice the optimal solution. The
greedy solution works only if the distances between cities follow Triangular Inequality (Dis-
tance between two points is always smaller than sum of distances through a third point).
531
Chapter 61. K Centers Problem Set 1 (Greedy Approximate Algorithm)
532
Chapter 61. K Centers Problem Set 1 (Greedy Approximate Algorithm)
Source:
http://algo2.iti.kit.edu/vanstee/courses/kcenter.pdf
This article is contributed by Harshit. Please write comments if you find anything incorrect,
or you want to share more information about the topic discussed above
Source
https://www.geeksforgeeks.org/k-centers-problem-set-1-greedy-approximate-algorithm/
533
Chapter 62
Ford-Fulkerson Algorithm
The following is simple idea of Ford-Fulkerson algorithm:
1) Start with initial flow as 0.
2) While there is a augmenting path from source to sink.
Add this path-flow to flow.
534
Chapter 62. Ford-Fulkerson Algorithm for Maximum Flow Problem
3) Return flow.
Time Complexity: Time complexity of the above algorithm is O(max_flow * E). We run
a loop while there is an augmenting path. In worst case, we may add 1 unit flow in every
iteration. Therefore the time complexity becomes O(max_flow * E).
How to implement the above simple algorithm?
Let us first define the concept of Residual Graph which is needed for understanding the
implementation.
Residual Graph of a flow network is a graph which indicates additional possible flow. If
there is a path from source to sink in residual graph, then it is possible to add flow. Every
edge of a residual graph has a value called residual capacity which is equal to original
capacity of the edge minus current flow. Residual capacity is basically the current capacity
of the edge.
Let us now talk about implementation details. Residual capacity is 0 if there is no edge
between two vertices of residual graph. We can initialize the residual graph as original graph
as there is no initial flow and initially residual capacity is equal to original capacity. To find
an augmenting path, we can either do a BFS or DFS of the residual graph. We have used
BFS in below implementation. Using BFS, we can find out if there is a path from source
to sink. BFS also builds parent[] array. Using the parent[] array, we traverse through the
found path and find possible flow through this path by finding minimum residual capacity
along the path. We later add the found path flow to overall flow.
The important thing is, we need to update residual capacities in the residual graph. We
subtract path flow from all edges along the path and we add path flow along the reverse
edges We need to add path flow along reverse edges because may later need to send flow in
reverse direction (See following link for example).
https://www.geeksforgeeks.org/max-flow-problem-introduction/
Below is the implementation of Ford-Fulkerson algorithm. To keep things simple, graph is
represented as a 2D matrix.
C++
535
Chapter 62. Ford-Fulkerson Algorithm for Maximum Flow Problem
memset(visited, 0, sizeof(visited));
// Create a queue, enqueue source vertex and mark source vertex
// as visited
queue <int> q;
q.push(s);
visited[s] = true;
parent[s] = -1;
// Standard BFS Loop
while (!q.empty())
{
int u = q.front();
q.pop();
for (int v=0; v<V; v++)
{
if (visited[v]==false && rGraph[u][v] > 0)
{
q.push(v);
parent[v] = u;
visited[v] = true;
}
}
}
// If we reached sink in BFS starting from source, then return
// true, else false
return (visited[t] == true);
}
// Returns the maximum flow from s to t in the given graph
int fordFulkerson(int graph[V][V], int s, int t)
{
int u, v;
// Create a residual graph and fill the residual graph with
// given capacities in the original graph as residual capacities
// in residual graph
int rGraph[V][V]; // Residual graph where rGraph[i][j] indicates
// residual capacity of edge from i to j (if there
// is an edge. If rGraph[i][j] is 0, then there is not)
for (u = 0; u < V; u++)
for (v = 0; v < V; v++)
rGraph[u][v] = graph[u][v];
int parent[V]; // This array is filled by BFS and to store path
536
Chapter 62. Ford-Fulkerson Algorithm for Maximum Flow Problem
537
Chapter 62. Ford-Fulkerson Algorithm for Maximum Flow Problem
Java
538
Chapter 62. Ford-Fulkerson Algorithm for Maximum Flow Problem
539
Chapter 62. Ford-Fulkerson Algorithm for Maximum Flow Problem
}
// Add path flow to overall flow
max_flow += path_flow;
}
// Return the overall flow
return max_flow;
}
// Driver program to test above functions
public static void main (String[] args) throws java.lang.Exception
{
// Let us create a graph shown in the above example
int graph[][] =new int[][] { {0, 16, 13, 0, 0, 0},
{0, 0, 10, 12, 0, 0},
{0, 4, 0, 0, 14, 0},
{0, 0, 9, 0, 0, 20},
{0, 0, 0, 7, 0, 4},
{0, 0, 0, 0, 0, 0}
};
MaxFlow m = new MaxFlow();
System.out.println("The maximum possible flow is " +
m.fordFulkerson(graph, 0, 5));
}
}
Python
540
Chapter 62. Ford-Fulkerson Algorithm for Maximum Flow Problem
541
Chapter 62. Ford-Fulkerson Algorithm for Maximum Flow Problem
s = parent[s]
# Add path flow to overall flow
max_flow += path_flow
# update residual capacities of the edges and reverse edges
# along the path
v = sink
while(v != source):
u = parent[v]
self.graph[u][v] -= path_flow
self.graph[v][u] += path_flow
v = parent[v]
return max_flow
# Create a graph given in the above diagram
graph = [[0, 16, 13, 0, 0, 0],
[0, 0, 10, 12, 0, 0],
[0, 4, 0, 0, 14, 0],
[0, 0, 9, 0, 0, 20],
[0, 0, 0, 7, 0, 4],
[0, 0, 0, 0, 0, 0]]
g = Graph(graph)
source = 0; sink = 5
print ("The maximum possible flow is %d " % g.FordFulkerson(source, sink))
#This code is contributed by Neelam Yadav
Output:
542
Chapter 62. Ford-Fulkerson Algorithm for Maximum Flow Problem
Source
https://www.geeksforgeeks.org/ford-fulkerson-algorithm-for-maximum-flow-problem/
543
Chapter 63
Find maximum number of edge disjoint paths between two vertices - GeeksforGeeks
Given a directed graph and two vertices in it, source ‘s’ and destination ‘t’, find out the
maximum number of edge disjoint paths from s to t. Two paths are said edge disjoint if
they don’t share any edge.
There can be maximum two edge disjoint paths from source 0 to destination 7 in the above
graph. Two edge disjoint paths are highlighted below in red and blue colors are 0-2-6-7 and
0-3-6-5-7.
544
Chapter 63. Find maximum number of edge disjoint paths between two vertices
Note that the paths may be different, but the maximum number is same. For example, in
the above diagram, another possible set of paths is 0-1-2-6-7 and 0-3-6-5-7 respectively.
This problem can be solved by reducing it to maximum flow problem. Following are steps.
1) Consider the given source and destination as source and sink in flow network. Assign
unit capacity to each edge.
2) Run Ford-Fulkerson algorithm to find the maximum flow from source to sink.
3) The maximum flow is equal to the maximum number of edge-disjoint paths.
When we run Ford-Fulkerson, we reduce the capacity by a unit. Therefore, the edge can
not be used again. So the maximum flow is equal to the maximum number of edge-disjoint
paths.
Following is C++ implementation of the above algorithm. Most of the code is taken from
here.
C/C++
545
Chapter 63. Find maximum number of edge disjoint paths between two vertices
q.push(s);
visited[s] = true;
parent[s] = -1;
// Standard BFS Loop
while (!q.empty())
{
int u = q.front();
q.pop();
for (int v=0; v<V; v++)
{
if (visited[v]==false && rGraph[u][v] > 0)
{
q.push(v);
parent[v] = u;
visited[v] = true;
}
}
}
// If we reached sink in BFS starting from source, then return
// true, else false
return (visited[t] == true);
}
// Returns tne maximum number of edge-disjoint paths from s to t.
// This function is copy of forFulkerson() discussed at http://goo.gl/wtQ4Ks
int findDisjointPaths(int graph[V][V], int s, int t)
{
int u, v;
// Create a residual graph and fill the residual graph with
// given capacities in the original graph as residual capacities
// in residual graph
int rGraph[V][V]; // Residual graph where rGraph[i][j] indicates
// residual capacity of edge from i to j (if there
// is an edge. If rGraph[i][j] is 0, then there is not)
for (u = 0; u < V; u++)
for (v = 0; v < V; v++)
rGraph[u][v] = graph[u][v];
int parent[V]; // This array is filled by BFS and to store path
int max_flow = 0; // There is no flow initially
// Augment the flow while tere is path from source to sink
while (bfs(rGraph, s, t, parent))
546
Chapter 63. Find maximum number of edge disjoint paths between two vertices
{
// Find minimum residual capacity of the edges along the
// path filled by BFS. Or we can say find the maximum flow
// through the path found.
int path_flow = INT_MAX;
for (v=t; v!=s; v=parent[v])
{
u = parent[v];
path_flow = min(path_flow, rGraph[u][v]);
}
// update residual capacities of the edges and reverse edges
// along the path
for (v=t; v != s; v=parent[v])
{
u = parent[v];
rGraph[u][v] -= path_flow;
rGraph[v][u] += path_flow;
}
// Add path flow to overall flow
max_flow += path_flow;
}
// Return the overall flow (max_flow is equal to maximum
// number of edge-disjoint paths)
return max_flow;
}
// Driver program to test above functions
int main()
{
// Let us create a graph shown in the above example
int graph[V][V] = { {0, 1, 1, 1, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0},
{0, 0, 0, 1, 0, 0, 1, 0},
{0, 0, 0, 0, 0, 0, 1, 0},
{0, 0, 1, 0, 0, 0, 0, 1},
{0, 1, 0, 0, 0, 0, 0, 1},
{0, 0, 0, 0, 0, 1, 0, 1},
{0, 0, 0, 0, 0, 0, 0, 0}
};
int s = 0;
int t = 7;
cout << "There can be maximum " << findDisjointPaths(graph, s, t)
<< " edge-disjoint paths from " << s <<" to "<< t ;
547
Chapter 63. Find maximum number of edge disjoint paths between two vertices
return 0;
}
Python
548
Chapter 63. Find maximum number of edge disjoint paths between two vertices
visited[ind] = True
parent[ind] = u
# If we reached sink in BFS starting from source, then return
# true, else false
return True if visited[t] else False
# Returns tne maximum number of edge-disjoint paths from
#s to t in the given graph
def findDisjointPaths(self, source, sink):
# This array is filled by BFS and to store path
parent = [-1]*(self.ROW)
max_flow = 0 # There is no flow initially
# Augment the flow while there is path from source to sink
while self.BFS(source, sink, parent) :
# Find minimum residual capacity of the edges along the
# path filled by BFS. Or we can say find the maximum flow
# through the path found.
path_flow = float("Inf")
s = sink
while(s != source):
path_flow = min (path_flow, self.graph[parent[s]][s])
s = parent[s]
# Add path flow to overall flow
max_flow += path_flow
# update residual capacities of the edges and reverse edges
# along the path
v = sink
while(v != source):
u = parent[v]
self.graph[u][v] -= path_flow
self.graph[v][u] += path_flow
v = parent[v]
return max_flow
# Create a graph given in the above diagram
graph = [[0, 1, 1, 1, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 0],
549
Chapter 63. Find maximum number of edge disjoint paths between two vertices
[0, 0, 0, 1, 0, 0, 1, 0],
[0, 0, 0, 0, 0, 0, 1, 0],
[0, 0, 1, 0, 0, 0, 0, 1],
[0, 1, 0, 0, 0, 0, 0, 1],
[0, 0, 0, 0, 0, 1, 0, 1],
[0, 0, 0, 0, 0, 0, 0, 0]]
g = Graph(graph)
source = 0; sink = 7
print ("There can be maximum %d edge-disjoint paths from %d to %d" %
(g.findDisjointPaths(source, sink), source, sink))
#This code is contributed by Neelam Yadav
Output:
Source
https://www.geeksforgeeks.org/find-edge-disjoint-paths-two-vertices/
550
Chapter 64
551
Chapter 64. Find minimum s-t cut in a flow network
The max-flow min-cut theorem states that in a flow network, the amount of maximum flow
is equal to capacity of the minimum cut. See CLRS book for proof of this theorem.
From Ford-Fulkerson, we get capacity of minimum cut. How to print all edges that form
the minimum cut? The idea is to use residual graph.
Following are steps to print all edges of the minimum cut.
1) Run Ford-Fulkerson algorithm and consider the final residual graph.
2) Find the set of vertices that are reachable from the source in the residual graph.
3) All edges which are from a reachable vertex to non-reachable vertex are minimum cut
edges. Print all such edges.
Following is C++ implementation of the above approach.
C++
552
Chapter 64. Find minimum s-t cut in a flow network
553
Chapter 64. Find minimum s-t cut in a flow network
{
u = parent[v];
path_flow = min(path_flow, rGraph[u][v]);
}
// update residual capacities of the edges and reverse edges
// along the path
for (v=t; v != s; v=parent[v])
{
u = parent[v];
rGraph[u][v] -= path_flow;
rGraph[v][u] += path_flow;
}
}
// Flow is maximum now, find vertices reachable from s
bool visited[V];
memset(visited, false, sizeof(visited));
dfs(rGraph, s, visited);
// Print all edges that are from a reachable vertex to
// non-reachable vertex in the original graph
for (int i = 0; i < V; i++)
for (int j = 0; j < V; j++)
if (visited[i] && !visited[j] && graph[i][j])
cout << i << " - " << j << endl;
return;
}
// Driver program to test above functions
int main()
{
// Let us create a graph shown in the above example
int graph[V][V] = { {0, 16, 13, 0, 0, 0},
{0, 0, 10, 12, 0, 0},
{0, 4, 0, 0, 14, 0},
{0, 0, 9, 0, 0, 20},
{0, 0, 0, 7, 0, 4},
{0, 0, 0, 0, 0, 0}
};
minCut(graph, 0, 5);
return 0;
}
Java
554
Chapter 64. Find minimum s-t cut in a flow network
555
Chapter 64. Find minimum s-t cut in a flow network
556
Chapter 64. Find minimum s-t cut in a flow network
dfs(rGraph, s, isVisited);
// Print all edges that are from a reachable vertex to
// non-reachable vertex in the original graph
for (int i = 0; i < graph.length; i++) {
for (int j = 0; j < graph.length; j++) {
if (graph[i][j] > 0 && isVisited[i] && !isVisited[j]) {
System.out.println(i + " - " + j);
}
}
}
}
//Driver Program
public static void main(String args[]) {
// Let us create a graph shown in the above example
int graph[][] = { {0, 16, 13, 0, 0, 0},
{0, 0, 10, 12, 0, 0},
{0, 4, 0, 0, 14, 0},
{0, 0, 9, 0, 0, 20},
{0, 0, 0, 7, 0, 4},
{0, 0, 0, 0, 0, 0}
};
minCut(graph, 0, 5);
}
}
// This code is contributed by Himanshu Shekhar
Python
557
Chapter 64. Find minimum s-t cut in a flow network
558
Chapter 64. Find minimum s-t cut in a flow network
s = sink
while(s != source):
path_flow = min (path_flow, self.graph[parent[s]][s])
s = parent[s]
# Add path flow to overall flow
max_flow += path_flow
# update residual capacities of the edges and reverse edges
# along the path
v = sink
while(v != source):
u = parent[v]
self.graph[u][v] -= path_flow
self.graph[v][u] += path_flow
v = parent[v]
# print the edges which initially had weights
# but now have 0 weight
for i in range(self.ROW):
for j in range(self.COL):
if self.graph[i][j] == 0 and self.org_graph[i][j] > 0:
print str(i) + " - " + str(j)
# Create a graph given in the above diagram
graph = [[0, 16, 13, 0, 0, 0],
[0, 0, 10, 12, 0, 0],
[0, 4, 0, 0, 14, 0],
[0, 0, 9, 0, 0, 20],
[0, 0, 0, 7, 0, 4],
[0, 0, 0, 0, 0, 0]]
g = Graph(graph)
source = 0; sink = 5
g.minCut(source, sink)
# This code is contributed by Neelam Yadav
Output:
1 - 3
4 - 3
4 - 5
References:
559
Chapter 64. Find minimum s-t cut in a flow network
http://www.stanford.edu/class/cs97si/08-network-flow-problems.pdf
http://www.cs.princeton.edu/courses/archive/spring06/cos226/lectures/maxflow.pdf
Source
https://www.geeksforgeeks.org/minimum-cut-in-a-directed-graph/
560
Chapter 65
561
Chapter 65. Maximum Bipartite Matching
562
Chapter 65. Maximum Bipartite Matching
Extra space can be be reduced and code can be simplified using the fact that the graph is
bipartite and capacity of every edge is either 0 or 1. The idea is to use DFS traversal to
find a job for an applicant (similar to augmenting path in Ford-Fulkerson). We call bpm()
for every applicant, bpm() is the DFS based function that tries all possibilities to assign a
job to the applicant.
In bpm(), we one by one try all jobs that an applicant ‘u’ is interested in until we find a job,
or all jobs are tried without luck. For every job we try, we do following.
If a job is not assigned to anybody, we simply assign it to the applicant and return true. If a
job is assigned to somebody else say x, then we recursively check whether x can be assigned
some other job. To make sure that x doesn’t get the same job again, we mark the job ‘v’ as
seen before we make recursive call for x. If x can get other job, we change the applicant for
job ‘v’ and return true. We use an array maxR[0..N-1] that stores the applicants assigned
to different jobs.
If bmp() returns true, then it means that there is an augmenting path in flow network and
1 unit of flow is added to the result in maxBPM().
C++
563
Chapter 65. Maximum Bipartite Matching
564
Chapter 65. Maximum Bipartite Matching
int main()
{
// Let us create a bpGraph
// shown in the above example
bool bpGraph[M][N] = {{0, 1, 1, 0, 0, 0},
{1, 0, 0, 1, 0, 0},
{0, 0, 1, 0, 0, 0},
{0, 0, 1, 1, 0, 0},
{0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 1}};
cout << "Maximum number of applicants that can get job is "
<< maxBPM(bpGraph);
return 0;
}
Java
565
Chapter 65. Maximum Bipartite Matching
// If job 'v' is not assigned to
// an applicant OR previously
// assigned applicant for job v (which
// is matchR[v]) has an alternate job available.
// Since v is marked as visited in the
// above line, matchR[v] in the following
// recursive call will not get job 'v' again
if (matchR[v] < 0 || bpm(bpGraph, matchR[v],
seen, matchR))
{
matchR[v] = u;
return true;
}
}
}
return false;
}
// Returns maximum number
// of matching from M to N
int maxBPM(boolean bpGraph[][])
{
// An array to keep track of the
// applicants assigned to jobs.
// The value of matchR[i] is the
// applicant number assigned to job i,
// the value -1 indicates nobody is assigned.
int matchR[] = new int[N];
// Initially all jobs are available
for(int i = 0; i < N; ++i)
matchR[i] = -1;
// Count of jobs assigned to applicants
int result = 0;
for (int u = 0; u < M; u++)
{
// Mark all jobs as not seen
// for next applicant.
boolean seen[] =new boolean[N] ;
for(int i = 0; i < N; ++i)
seen[i] = false;
// Find if the applicant 'u' can get a job
if (bpm(bpGraph, u, seen, matchR))
result++;
}
566
Chapter 65. Maximum Bipartite Matching
return result;
}
// Driver Code
public static void main (String[] args)
throws java.lang.Exception
{
// Let us create a bpGraph shown
// in the above example
boolean bpGraph[][] = new boolean[][]{
{false, true, true,
false, false, false},
{true, false, false,
true, false, false},
{false, false, true,
false, false, false},
{false, false, true,
true, false, false},
{false, false, false,
false, false, false},
{false, false, false,
false, false, true}};
GFG m = new GFG();
System.out.println( "Maximum number of applicants that can"+
" get job is "+m.maxBPM(bpGraph));
}
}
Python
567
Chapter 65. Maximum Bipartite Matching
# If applicant u is interested
# in job v and v is not seen
if self.graph[u][v] and seen[v] == False:
# Mark v as visited
seen[v] = True
'''If job 'v' is not assigned to
an applicant OR previously assigned
applicant for job v (which is matchR[v])
has an alternate job available.
Since v is marked as visited in the
above line, matchR[v] in the following
recursive call will not get job 'v' again'''
if matchR[v] == -1 or self.bpm(matchR[v],
matchR, seen):
matchR[v] = u
return True
return False
# Returns maximum number of matching
def maxBPM(self):
'''An array to keep track of the
applicants assigned to jobs.
The value of matchR[i] is the
applicant number assigned to job i,
the value -1 indicates nobody is assigned.'''
matchR = [-1] * self.jobs
# Count of jobs assigned to applicants
result = 0
for i in range(self.ppl):
# Mark all jobs as not seen for next applicant.
seen = [False] * self.jobs
# Find if the applicant 'u' can get a job
if self.bpm(i, matchR, seen):
result += 1
return result
bpGraph =[[0, 1, 1, 0, 0, 0],
[1, 0, 0, 1, 0, 0],
[0, 0, 1, 0, 0, 0],
[0, 0, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 0],
568
Chapter 65. Maximum Bipartite Matching
[0, 0, 0, 0, 0, 1]]
g = GFG(bpGraph)
print ("Maximum number of applicants that can get job is %d " % g.maxBPM())
# This code is contributed by Neelam Yadav
C#
569
Chapter 65. Maximum Bipartite Matching
return true;
}
}
}
return false;
}
// Returns maximum number of
// matching from M to N
int maxBPM(bool [,]bpGraph)
{
// An array to keep track of the
// applicants assigned to jobs.
// The value of matchR[i] is the
// applicant number assigned to job i,
// the value -1 indicates nobody is assigned.
int []matchR = new int[N];
// Initially all jobs are available
for(int i = 0; i < N; ++i)
matchR[i] = -1;
// Count of jobs assigned to applicants
int result = 0;
for (int u = 0; u < M; u++)
{
// Mark all jobs as not
// seen for next applicant.
bool []seen = new bool[N] ;
for(int i = 0; i < N; ++i)
seen[i] = false;
// Find if the applicant
// 'u' can get a job
if (bpm(bpGraph, u, seen, matchR))
result++;
}
return result;
}
// Driver Code
public static void Main ()
{
// Let us create a bpGraph shown
// in the above example
bool [,]bpGraph = new bool[,]
{{false, true, true,
false, false, false},
570
Chapter 65. Maximum Bipartite Matching
Output :
Source
https://www.geeksforgeeks.org/maximum-bipartite-matching/
571
Chapter 66
0 2 0
3 0 1
2 4 0
The above is the input format. We call the above matrix M. Each value M[i; j] represents
the number of packets Transmitter ‘i’ has to send to Receiver ‘j’. The output should be:
Note that the maximum number of packets that can be transferred in any slot is min(M,
N).
Algorithm:
The channel assignment problem between sender and receiver can be easily transformed
into Maximum Bipartite Matching(MBP) problem that can be solved by converting it into
a flow network.
572
Chapter 66. Channel Assignment Problem
#include <iostream>
#include <string.h>
#include <vector>
#define M 3
#define N 4
using namespace std;
// A Depth First Search based recursive function that returns true
573
Chapter 66. Channel Assignment Problem
574
Chapter 66. Channel Assignment Problem
Output:
This article is contributed by Vignesh Narayanan. Please write comments if you find any-
thing incorrect, or you want to share more information about the topic discussed above
Source
https://www.geeksforgeeks.org/channel-assignment-problem/
575
Chapter 67
The above union() and find() are naive and the worst case time complexity is linear. The
trees created to represent subsets can be skewed and can become like a linked list. Following
is an example worst case scenario.
576
Chapter 67. Union Find Algorithm Set 2 (Union By Rank and Path Compression)
Do Union(0, 1)
1 2 3
/
0
Do Union(1, 2)
2 3
/
1
/
0
Do Union(2, 3)
3
/
2
/
1
/
0
The above operations can be optimized to O(Log n) in worst case. The idea is to always
attach smaller depth tree under the root of the deeper tree. This technique is called union
by rank. The term rank is preferred instead of height because if path compression technique
(we have discussed it below) is used, then rank is not always equal to height. Also, size (in
place of height) of trees can also be used as rank. Using size as rank also yields worst case
time complexity as O(Logn) (See thisfor proof)
Do Union(0, 1)
1 2 3
/
0
Do Union(1, 2)
1 3
/ \
0 2
577
Chapter 67. Union Find Algorithm Set 2 (Union By Rank and Path Compression)
Do Union(2, 3)
1
/ | \
0 2 3
The second optimization to naive method is Path Compression. The idea is to flatten the
tree when find() is called. When find() is called for an element x, root of the tree is returned.
The find() operation traverses up from x to find root. The idea of path compression is to
make the found root as parent of x so that we don’t have to traverse all intermediate nodes
again. If x is root of a subtree, then path (to root) from all nodes under x also compresses.
9
/ / \ \
4 5 6 3
/ / \ / \
0 7 8 1 2
The two techniques complement each other. The time complexity of each operation becomes
even smaller than O(Logn). In fact, amortized time complexity effectively becomes small
constant.
Following is union by rank and path compression based implementation to find a cycle in a
graph.
C++
// A union by rank and path compression based program to detect cycle in a graph
#include <stdio.h>
#include <stdlib.h>
// a structure to represent an edge in the graph
struct Edge
{
int src, dest;
578
Chapter 67. Union Find Algorithm Set 2 (Union By Rank and Path Compression)
};
// a structure to represent a graph
struct Graph
{
// V-> Number of vertices, E-> Number of edges
int V, E;
// graph is represented as an array of edges
struct Edge* edge;
};
struct subset
{
int parent;
int rank;
};
// Creates a graph with V vertices and E edges
struct Graph* createGraph(int V, int E)
{
struct Graph* graph = (struct Graph*) malloc( sizeof(struct Graph) );
graph->V = V;
graph->E = E;
graph->edge = (struct Edge*) malloc( graph->E * sizeof( struct Edge ) );
return graph;
}
// A utility function to find set of an element i
// (uses path compression technique)
int find(struct subset subsets[], int i)
{
// find root and make root as parent of i (path compression)
if (subsets[i].parent != i)
subsets[i].parent = find(subsets, subsets[i].parent);
return subsets[i].parent;
}
// A function that does union of two sets of x and y
// (uses union by rank)
void Union(struct subset subsets[], int x, int y)
{
int xroot = find(subsets, x);
int yroot = find(subsets, y);
579
Chapter 67. Union Find Algorithm Set 2 (Union By Rank and Path Compression)
// Attach smaller rank tree under root of high rank tree
// (Union by Rank)
if (subsets[xroot].rank < subsets[yroot].rank)
subsets[xroot].parent = yroot;
else if (subsets[xroot].rank > subsets[yroot].rank)
subsets[yroot].parent = xroot;
// If ranks are same, then make one as root and increment
// its rank by one
else
{
subsets[yroot].parent = xroot;
subsets[xroot].rank++;
}
}
// The main function to check whether a given graph contains cycle or not
int isCycle( struct Graph* graph )
{
int V = graph->V;
int E = graph->E;
// Allocate memory for creating V sets
struct subset *subsets =
(struct subset*) malloc( V * sizeof(struct subset) );
for (int v = 0; v < V; ++v)
{
subsets[v].parent = v;
subsets[v].rank = 0;
}
// Iterate through all edges of graph, find sets of both
// vertices of every edge, if sets are same, then there is
// cycle in graph.
for(int e = 0; e < E; ++e)
{
int x = find(subsets, graph->edge[e].src);
int y = find(subsets, graph->edge[e].dest);
if (x == y)
return 1;
Union(subsets, x, y);
}
return 0;
}
580
Chapter 67. Union Find Algorithm Set 2 (Union By Rank and Path Compression)
Java
581
Chapter 67. Union Find Algorithm Set 2 (Union By Rank and Path Compression)
582
Chapter 67. Union Find Algorithm Set 2 (Union By Rank and Path Compression)
583
Chapter 67. Union Find Algorithm Set 2 (Union By Rank and Path Compression)
graph.edge[2].src = 0;
graph.edge[2].dest = 2;
if (graph.isCycle(graph) == 1)
System.out.println("Graph contains cycle");
else
System.out.println("Graph doesn't contain cycle");
}
}
// This code is contributed
// by ashwani khemani
Output:
Related Articles :
Union-Find Algorithm Set 1 (Detect Cycle in a an Undirected Graph)
Disjoint Set Data Structures (Java Implementation)
Greedy Algorithms Set 2 (Kruskal’s Minimum Spanning Tree Algorithm)
Job Sequencing Problem Set 2 (Using Disjoint Set)
References:
http://en.wikipedia.org/wiki/Disjoint-set_data_structure
IITD Video Lecture
Improved By : DeepeshThakur, ashwani khemani
Source
https://www.geeksforgeeks.org/union-find-algorithm-set-2-union-by-rank/
584
Chapter 68
Karger’s algorithm for Minimum Cut Set 1 (Introduction and Implementation) - Geeks-
forGeeks
Given an undirected and unweighted graph, find the smallest cut (smallest number of edges
that disconnects the graph into two components).
The input graph may have parallel edges.
For example consider the following example, the smallest cut has 2 edges.
A Simple Solution use Max-Flow based s-t cut algorithm to find minimum cut. Consider
every pair of vertices as source ‘s’ and sink ‘t’, and call minimum s-t cut algorithm to find
the s-t cut. Return minimum of all s-t cuts. Best possible time complexity of this algorithm
is O(V5 ) for a graph. [How? there are total possible V2 pairs and s-t cut algorithm for one
pair takes O(V*E) time and E = O(V2 )].
Below is simple Karger’s Algorithm for this purpose. Below Karger’s algorithm can be
implemented in O(E) = O(V2 ) time.
585
Chapter 68. Karger’s algorithm for Minimum Cut
Let the next randomly picked edge be ‘d’. We remove this edge and combine vertices (0,1)
and 3.
Now graph has two vertices, so we stop. The number of edges in the resultant graph is the
cut produced by Karger’s algorithm.
Karger’s algorithm is a Monte Carlo algorithm and cut produced by it may not
be minimum. For example, the following diagram shows that a different order of picking
random edges produces a min-cut of size 3.
586
Chapter 68. Karger’s algorithm for Minimum Cut
587
Chapter 68. Karger’s algorithm for Minimum Cut
};
// A structure to represent a subset for union-find
struct subset
{
int parent;
int rank;
};
// Function prototypes for union-find (These functions are defined
// after kargerMinCut() )
int find(struct subset subsets[], int i);
void Union(struct subset subsets[], int x, int y);
// A very basic implementation of Karger's randomized
// algorithm for finding the minimum cut. Please note
// that Karger's algorithm is a Monte Carlo Randomized algo
// and the cut returned by the algorithm may not be
// minimum always
int kargerMinCut(struct Graph* graph)
{
// Get data of given graph
int V = graph->V, E = graph->E;
Edge *edge = graph->edge;
// Allocate memory for creating V subsets.
struct subset *subsets = new subset[V];
// Create V subsets with single elements
for (int v = 0; v < V; ++v)
{
subsets[v].parent = v;
subsets[v].rank = 0;
}
// Initially there are V vertices in
// contracted graph
int vertices = V;
// Keep contracting vertices until there are
// 2 vertices.
while (vertices > 2)
{
// Pick a random edge
int i = rand() % E;
// Find vertices (or sets) of two corners
// of current edge
588
Chapter 68. Karger’s algorithm for Minimum Cut
589
Chapter 68. Karger’s algorithm for Minimum Cut
590
Chapter 68. Karger’s algorithm for Minimum Cut
// add edge 0-2
graph->edge[1].src = 0;
graph->edge[1].dest = 2;
// add edge 0-3
graph->edge[2].src = 0;
graph->edge[2].dest = 3;
// add edge 1-3
graph->edge[3].src = 1;
graph->edge[3].dest = 3;
// add edge 2-3
graph->edge[4].src = 2;
graph->edge[4].dest = 3;
// Use a different seed value for every run.
srand(time(NULL));
printf("\nCut found by Karger's randomized algo is %d\n",
kargerMinCut(graph));
return 0;
}
Output:
Note that the above program is based on outcome of a random function and may
produce different output.
In this post, we have discussed simple Karger’s algorithm and have seen that the algorithm
doesn’t always produce min-cut. The above algorithm produces min-cut with probability
greater or equal to that 1/(n2 ). See next post on Analysis and Applications of Karger’s
Algortihm, applications, proof of this probability and improvements are discussed.
References:
http://en.wikipedia.org/wiki/Karger%27s_algorithm
https://www.youtube.com/watch?v=P0l8jMDQTEQ
https://www.cs.princeton.edu/courses/archive/fall13/cos521/lecnotes/lec2final.pdf
http://web.stanford.edu/class/archive/cs/cs161/cs161.1138/lectures/11/Small11.pdf
591
Chapter 68. Karger’s algorithm for Minimum Cut
Source
https://www.geeksforgeeks.org/kargers-algorithm-for-minimum-cut-set-1-introduction-and-implementation/
592
Chapter 69
Karger’s algorithm for Minimum Cut Set 2 (Analysis and Applications) - GeeksforGeeks
We have introduced and discussed below Karger’s algorithm in set 1.
As discussed in the previous post,Karger’s algorithmdoesn’t always find min cut. In this
post, the probability of finding min-cut is discussed.
Probability that the cut produced by Karger’s Algorithm is Min-Cut is greater
than or equal to 1/(n2 )
Proof:
Let there be a unique Min-Cut of given graph and let there be C edges in the Min-Cut and
the edges be {e1 , e2 , e3 , .. ec }. The Karger’s algorithm would produce this Min-Cut if and
only if none of the edges in set {e1 , e2 , e3 , .. ec } is removed in iterations in the main while
loop of above algorithm.
593
Chapter 69. Karger’s algorithm for Minimum Cut Set 2 (Analysis and Applications)
..................
..................
The cut produced by Karger's algorithm would be a min-cut if none of the above
events happen.
594
Chapter 69. Karger’s algorithm for Minimum Cut Set 2 (Analysis and Applications)
Since there are total (n-1) edges left now and number of cut edges is still c,
we can replace n by n-1 in inequality (1). So we get.
P[S2' | S1' ] >= (1 - 2/(n-1))
595
Chapter 69. Karger’s algorithm for Minimum Cut Set 2 (Analysis and Applications)
with 10 nodes, the probability of finding the min-cut is greater than or equal to 1/100. The
probability can be increased by repeated runs of basic algorithm and return minimum of all
cuts found.
Applications:
1) In war situation, a party would be interested in finding minimum number of links that
break communication network of enemy.
2) The min-cut problem can be used to study reliability of a network (smallest number of
edges that can fail).
3) Study of network optimization (find a maximum flow).
4) Clustering problems (edges like associations rules) Matching problems (an NCalgorithm
for min-cut in directed graphs would result in an NCalgorithm for maximum matching in
bipartite graphs)
5) Matching problems (an NC algorithm for min-cut in directed graphs would result in an
NC algorithm for maximum matching in bipartite graphs)
Sources:
https://www.youtube.com/watch?v=-UuivvyHPas
http://disi.unal.edu.co/~gjhernandezp/psc/lectures/02/MinCut.pdf
Source
https://www.geeksforgeeks.org/kargers-algorithm-for-minimum-cut-set-2-analysis-and-applications/
596
Chapter 70
597
Chapter 70. Hopcroft Karp Algorithm for Maximum Matching Set 1 (Introduction)
In the initial graph all single edges are augmenting paths and we can pick in any order. In
the middle stage, there is only one augmenting path. We remove matching edges of this
path from M and add not-matching edges. In final matching, there are no augmenting paths
so the matching is maximum.
Implementation of Hopcroft Karp algorithm is discussed in set 2.
Hopcroft–Karp Algorithm for Maximum Matching Set 2 (Implementation)
References:
https://en.wikipedia.org/wiki/Hopcroft%E2%80%93Karp_algorithm
http://www.dis.uniroma1.it/~leon/tcs/lecture2.pdf
598
Chapter 70. Hopcroft Karp Algorithm for Maximum Matching Set 1 (Introduction)
Source
https://www.geeksforgeeks.org/hopcroft-karp-algorithm-for-maximum-matching-set-1-introduction/
599
Chapter 71
The idea is to use BFS (Breadth First Search) to find augmenting paths. Since BFS traverses
level by level, it is used to divide the graph in layers of matching and not matching edges. A
dummy vertex NIL is added that is connected to all vertices on left side and all vertices on
right side. Following arrays are used to find augmenting path. Distance to NIL is initialized
as INF (infinite). If we start from dummy vertex and come back to it using alternating path
of distinct vertices, then there is an augmenting path.
1. pairU[]: An array of size m+1 where m is number of vertices on left side of Bipartite
Graph. pairU[u] stores pair of u on right side if u is matched and NIL otherwise.
2. pairV[]: An array of size n+1 where n is number of vertices on right side of Bipartite
Graph. pairV[v] stores pair of v on left side if v is matched and NIL otherwise.
600
Chapter 71. Hopcroft-Karp Algorithm for Maximum Matching Set 2 (Implementation)
3. dist[]: An array of size m+1 where m is number of vertices on left side of Bipartite
Graph. dist[u] is initialized as 0 if u is not matching and INF (infinite) otherwise.
dist[] of NIL is also initialized as INF
Once an augmenting path is found, DFS (Depth First Search) is used to add augmenting
paths to current matching. DFS simply follows the distance array setup by BFS. It fills
values in pairU[u] and pairV[v] if v is next to u in BFS.
Below is C++ implementation of above Hopkroft Karp algorithm.
601
Chapter 71. Hopcroft-Karp Algorithm for Maximum Matching Set 2 (Implementation)
// Returns size of maximum matching
int BipGraph::hopcroftKarp()
{
// pairU[u] stores pair of u in matching where u
// is a vertex on left side of Bipartite Graph.
// If u doesn't have any pair, then pairU[u] is NIL
pairU = new int[m+1];
// pairV[v] stores pair of v in matching. If v
// doesn't have any pair, then pairU[v] is NIL
pairV = new int[n+1];
// dist[u] stores distance of left side vertices
// dist[u] is one more than dist[u'] if u is next
// to u'in augmenting path
dist = new int[m+1];
// Initialize NIL as pair of all vertices
for (int u=0; u<m; u++)
pairU[u] = NIL;
for (int v=0; v<n; v++)
pairV[v] = NIL;
// Initialize result
int result = 0;
// Keep updating the result while there is an
// augmenting path.
while (bfs())
{
// Find a free vertex
for (int u=1; u<=m; u++)
// If current vertex is free and there is
// an augmenting path from current vertex
if (pairU[u]==NIL && dfs(u))
result++;
}
return result;
}
// Returns true if there is an augmenting path, else returns
// false
bool BipGraph::bfs()
{
queue<int> Q; //an integer queue
602
Chapter 71. Hopcroft-Karp Algorithm for Maximum Matching Set 2 (Implementation)
603
Chapter 71. Hopcroft-Karp Algorithm for Maximum Matching Set 2 (Implementation)
604
Chapter 71. Hopcroft-Karp Algorithm for Maximum Matching Set 2 (Implementation)
Output:
The above implementation is mainly adopted from the algorithm provided on Wiki page of
Hopcroft Karp algorithm.
This article is contributed by Rahul Gupta. Please write comments if you find anything
incorrect, or you want to share more information about the topic discussed above
Improved By : am10
Source
https://www.geeksforgeeks.org/hopcroft-karp-algorithm-for-maximum-matching-set-2-implementation/
605
Chapter 72
Explanation :
Shortest distance from 0 to 0 is 0
Shortest distance from 0 to 1 is 0
Shortest distance from 0 to 2 is 1
..................
In normal BFSof a graph all edges have equal weight but in 0-1 BFS some edges may have
0 weight and some may have 1 weight. In this we will not use bool array to mark visited
nodes but at each step we will check for the optimal distance condition. We use double
ended queue to store the node. While performing BFS if a edge having weight = 0 is found
node is pushed at front of double ended queue and if a edge having weight = 1 is found, it
is pushed at back of double ended queue.
The approach is similar to Dijkstra that the if the shortest distance to node is relaxed
by the previous node then only it will be pushed in the queue.
The above idea works in all cases, when pop a vertex (like Dijkstra), it is the minimum
weight vertex among remaining vertices. If there is a 0 weight vertex adjacent to it, then this
606
Chapter 72. 0-1 BFS (Shortest Path in a Binary Weight Graph)
adjacent has same distance. If there is a 1 weight adjacent, then this adjacent has maximum
distance among all vertices in dequeue (because all other vertices are either adjacent of
currently popped vertex or adjacent of previously popped vertices).
Below is C++ implementation of the above idea.
607
Chapter 72. 0-1 BFS (Shortest Path in a Binary Weight Graph)
Output:
0 0 1 1 2 1 2 1 2
608
Chapter 72. 0-1 BFS (Shortest Path in a Binary Weight Graph)
This problem can also be solved by Dijkstra but the time complexity will be O(E + V Log
V) whereas by BFS it will be O(V+E).
Reference :
http://codeforces.com/blog/entry/22276
Source
https://www.geeksforgeeks.org/0-1-bfs-shortest-path-binary-graph/
609
Chapter 73
• Satisfiable : If the Boolean variables can be assigned values such that the formula
turns out to be TRUE, then we say that the formula is satisfiable.
• Unsatisfiable : If it is not possible to assign such values, then we say that the formula
is unsatisfiable.
Examples:
• , is unsatisfiable, because:
Note : Boolean satisfiability problem is NP-complete (For proof, refer lank”>Cook’s The-
orem).
610
Chapter 73. 2-Satisfiability (2-SAT) Problem
To understand this better, first let us see what is Conjunctive Normal Form (CNF) or also
known as Product of Sums (POS).
CNF : CNF is a conjunction (AND) of clauses, where every clause is a disjunction (OR).
Now, 2-SAT limits the problem of SAT to only those Boolean formula which are expressed
as a CNF with every clause having only 2 terms(also called 2-CNF).
Example:
Thus, Problem of 2-Satisfiabilty can be stated as:
Given CNF with each clause having only 2 terms, is it possible to assign such
values to the variables so that the CNF is TRUE?
Examples:
Input :
Output : The given expression is satisfiable.
(for x1 = FALSE, x2 = TRUE)
Input :
Output : The given expression is unsatisfiable.
(for all possible combinations of x1 and x2)
For the CNF value to come TRUE, value of every clause should be TRUE. Let one of the
clause be .
= TRUE
• If A = 0, B must be 1 i.e.
• If B = 0, A must be 1 i.e.
Thus,
= TRUE is equivalent to
Now, we can express the CNF as an Implication. So, we create an Implication Graph which
has 2 edges for every clause of the CNF.
611
Chapter 73. 2-Satisfiability (2-SAT) Problem
Note: The implication (if A then B) is equivalent to its contrapositive (if then ).
Now, consider the following cases:
612
Chapter 73. 2-Satisfiability (2-SAT) Problem
If we have
Thus, if we have a path in the Implication Graph, that is pretty much same as having a
direct edge.
CONCLUSION FROM IMPLEMENTATION POINT OF VIEW:
If both X and lie in the same SCC (Strongly Connected Component), the CNF is
unsatisfiable.
A Strongly Connected Component of a directed graph has nodes such that every node can
be reach from every another node in that SCC.
613
Chapter 73. 2-Satisfiability (2-SAT) Problem
// adds edges to form the original graph
void addEdges(int a, int b)
{
adj[a].push_back(b);
}
// add edges to form the inverse graph
void addEdgesInverse(int a, int b)
{
adjInv[b].push_back(a);
}
// for STEP 1 of Kosaraju's Algorithm
void dfsFirst(int u)
{
if(visited[u])
return;
visited[u] = 1;
for (int i=0;i<adj[u].size();i++)
dfsFirst(adj[u][i]);
s.push(u);
}
// for STEP 2 of Kosaraju's Algorithm
void dfsSecond(int u)
{
if(visitedInv[u])
return;
visitedInv[u] = 1;
for (int i=0;i<adjInv[u].size();i++)
dfsSecond(adjInv[u][i]);
scc[u] = counter;
}
// function to check 2-Satisfiability
void is2Satisfiable(int n, int m, int a[], int b[])
{
// adding edges to the graph
for(int i=0;i<m;i++)
{
// variable x is mapped to x
614
Chapter 73. 2-Satisfiability (2-SAT) Problem
615
Chapter 73. 2-Satisfiability (2-SAT) Problem
int n = s.top();
s.pop();
if (!visitedInv[n])
{
dfsSecond(n);
counter++;
}
}
for (int i=1;i<=n;i++)
{
// for any 2 vairable x and -x lie in
// same SCC
if(scc[i]==scc[i+n])
{
cout << "The given expression "
"is unsatisfiable." << endl;
return;
}
}
// no such variables x and -x exist which lie
// in same SCC
cout << "The given expression is satisfiable."
<< endl;
return;
}
// Driver function to test above functions
int main()
{
// n is the number of variables
// 2n is the total number of nodes
// m is the number of clauses
int n = 5, m = 7;
// each clause is of the form a or b
// for m clauses, we have a[m], b[m]
// representing a[i] or b[i]
// Note:
// 1 <= x <= N for an uncomplemented variable x
// -N <= x <= -1 for a complemented variable x
// -x is the complement of a variable x
// The CNF being handled is:
// '+' implies 'OR' and '*' implies 'AND'
616
Chapter 73. 2-Satisfiability (2-SAT) Problem
// (x1+x2)*(x2’+x3)*(x1’+x2’)*(x3+x4)*(x3’+x5)*
// (x4’+x5’)*(x3’+x4)
int a[] = {1, -2, -1, 3, -3, -4, -3};
int b[] = {2, 3, -2, 4, 5, -5, 4};
// We have considered the same example for which
// Implication Graph was made
is2Satisfiable(n, m, a, b);
return 0;
}
Output:
Input : n = 2, m = 3
a[] = {1, 2, -1}
b[] = {2, -1, -2}
Output : The given expression is satisfiable.
Input : n = 2, m = 4
a[] = {1, -1, 1, -1}
b[] = {2, 2, -2, -2}
Output : The given expression is unsatisfiable.
Source
https://www.geeksforgeeks.org/2-satisfiability-2-sat-problem/
617
Chapter 74
618
Chapter 74. A matrix probability question
619
Chapter 74. A matrix probability question
Java
620
Chapter 74. A matrix probability question
C#
621
Chapter 74. A matrix probability question
// matrix coordinate
static bool isSafe(int x, int y,
int m, int n)
{
return (x >= 0 && x < m &&
y >= 0 && y < n);
}
// Function to calculate probability
// that after N moves from a given
// position (x, y) in m x n matrix,
// boundaries of the matrix will
// not be crossed.
static double findProbability(int m, int n,
int x, int y,
int N)
{
// boundary crossed
if (! isSafe(x, y, m, n))
return 0.0;
// N steps taken
if (N == 0)
return 1.0;
// Initialize result
double prob = 0.0;
// move up
prob += findProbability(m, n, x - 1,
y, N - 1) * 0.25;
// move right
prob += findProbability(m, n, x, y + 1,
N - 1) * 0.25;
// move down
prob += findProbability(m, n, x + 1,
y, N - 1) * 0.25;
// move left
prob += findProbability(m, n, x, y - 1,
N - 1) * 0.25;
return prob;
}
622
Chapter 74. A matrix probability question
// Driver code
public static void Main ()
{
// matrix size
int m = 5, n = 5;
// coordinates of starting point
int i = 1, j = 1;
// Number of steps
int N = 2;
Console.Write("Probability is " +
findProbability(m, n, i,
j, N));
}
}
// This code is contributed by nitin mittal.
PHP
<?php
// PHP program to find the probability
// that we do not cross boundary of a
// matrix after N moves.
// check if (x, y) is valid
// matrix coordinate
function isSafe($x, $y, $m, $n)
{
return ($x >= 0 && $x < $m &&
$y >= 0 && $y < $n);
}
// Function to calculate probability
// that after N moves from a given
// position (x, y) in m x n matrix,
// boundaries of the matrix will
// not be crossed.
function findProbability($m, $n, $x,
$y, $N)
{
// boundary crossed
if (!isSafe($x, $y, $m, $n))
return 0.0;
623
Chapter 74. A matrix probability question
// N steps taken
if ($N == 0)
return 1.0;
// Initialize result
$prob = 0.0;
// move up
$prob += findProbability($m, $n, $x - 1,
$y, $N - 1) * 0.25;
// move right
$prob += findProbability($m, $n, $x,
$y + 1, $N - 1) * 0.25;
// move down
$prob += findProbability($m, $n, $x + 1,
$y, $N - 1) * 0.25;
// move left
$prob += findProbability($m, $n, $x,
$y - 1, $N - 1) * 0.25;
return $prob;
}
// Driver code
// matrix size
$m = 5; $n = 5;
// coordinates of starting point
$i = 1; $j = 1;
// Number of steps
$N = 2;
echo "Probability is ",
findProbability($m, $n, $i, $j, $N);
// This code is contributed by nitin mittal.
?>
Output :
Probability is 0.875
624
Chapter 74. A matrix probability question
This article is contributed by Aditya Goel. Please write comments if you find anything
incorrect, or you want to share more information about the topic discussed above
Improved By : KRV, nitin mittal
Source
https://www.geeksforgeeks.org/a-matrix-probability-question/
625
Chapter 75
626
Chapter 75. A Peterson Graph Problem
Examples:
Input : s = 'ABB'
Output: 016
Explanation: As we can see in the graph
the path from ABB is 016.
Input : s = 'AABE'
Output :-1
Explanation: As there is no path that
exists, hence output is -1.
627
Chapter 75. A Peterson Graph Problem
Output:
016
Source
https://www.geeksforgeeks.org/peterson-graph/
628
Chapter 76
In a Directed acyclic graph many a times we can have vertices which are unrelated to each
other because of which we can order them in many ways. These various topological sorting
629
Chapter 76. All Topological Sorts of a Directed Acyclic Graph
is important in many cases, for example if some relative weight is also available between the
vertices, which is to minimize then we need to take care of relative ordering as well as their
relative weight, which creates the need of checking through all possible topological ordering.
We can go through all possible ordering via backtracking , the algorithm step are as follows
:
630
Chapter 76. All Topological Sorts of a Directed Acyclic Graph
Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V];
// Initialising all indegree with 0
for (int i = 0; i < V; i++)
indegree.push_back(0);
}
// Utility function to add edge
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w); // Add w to v's list.
// increasing inner degree of w by 1
indegree[w]++;
}
// Main recursive function to print all possible
// topological sorts
void Graph::alltopologicalSortUtil(vector<int>& res,
bool visited[])
{
// To indicate whether all topological are found
// or not
bool flag = false;
for (int i = 0; i < V; i++)
{
// If indegree is 0 and not yet visited then
// only choose that vertex
if (indegree[i] == 0 && !visited[i])
{
// reducing indegree of adjacent vertices
list<int>:: iterator j;
for (j = adj[i].begin(); j != adj[i].end(); j++)
indegree[*j]--;
// including in result
res.push_back(i);
visited[i] = true;
alltopologicalSortUtil(res, visited);
// resetting visited, res and indegree for
// backtracking
visited[i] = false;
res.erase(res.end() - 1);
631
Chapter 76. All Topological Sorts of a Directed Acyclic Graph
632
Chapter 76. All Topological Sorts of a Directed Acyclic Graph
Java
633
Chapter 76. All Topological Sorts of a Directed Acyclic Graph
}
allTopologicalSortsUtil(visited, indegree, stack);
// resetting visited, res and indegree for
// backtracking
visited[i] = false;
stack.remove(stack.size() - 1);
for (int adjacent : this.adjListArray[i]) {
indegree[adjacent]++;
}
flag = true;
}
}
// We reach here if all vertices are visited.
// So we print the solution here
if (!flag) {
stack.forEach(i -> System.out.print(i + " "));
System.out.println();
}
}
// The function does all Topological Sort.
// It uses recursive alltopologicalSortUtil()
public void allTopologicalSorts() {
// Mark all the vertices as not visited
boolean[] visited = new boolean[this.V];
int[] indegree = new int[this.V];
for (int i = 0; i < this.V; i++) {
for (int var : this.adjListArray[i]) {
indegree[var]++;
}
}
ArrayList<Integer> stack = new ArrayList<>();
allTopologicalSortsUtil(visited, indegree, stack);
}
// Driver code
public static void main(String[] args) {
// Create a graph given in the above diagram
Graph graph = new Graph(6);
634
Chapter 76. All Topological Sorts of a Directed Acyclic Graph
graph.addEdge(5, 2);
graph.addEdge(5, 0);
graph.addEdge(4, 0);
graph.addEdge(4, 1);
graph.addEdge(2, 3);
graph.addEdge(3, 1);
System.out.println("All Topological sorts");
graph.allTopologicalSorts();
}
}
Output :
This articles is contributed by Utkarsh Trivedi. Please write comments if you find anything
incorrect, or you want to share more information about the topic discussed above
Improved By : sakshamcse
Source
https://www.geeksforgeeks.org/all-topological-sorts-of-a-directed-acyclic-graph/
635
Chapter 77
636
Chapter 77. Applications of Graph Data Structure
to the allocated process, or from requesting process to the requested resource. If this
leads to any formation of a cycle then a deadlock will occur.
Thus the development of algorithms to handle graphs is of major interest in the field of
computer science.
Source
https://www.geeksforgeeks.org/applications-of-graph-data-structure/
637
Chapter 78
Where is a parameter whose value is typically in the range 2 < < 3, although
occasionally it may lie outside these bounds and c is a proportionality constant.
The Barabási–Albert model is one of several proposed models that generate scale-free net-
works. It incorporates two important general concepts: growth and preferential attachment.
Both growth and preferential attachment exist widely in real networks. Growth means that
the number of nodes in the network increases over time.
Preferential attachment means that the more connected a node is, the more likely it is to
receive new links. Nodes with higher degree have stronger ability to grab links added to the
638
Chapter 78. Barabasi Albert Graph (for Scale Free Models)
attachment model.
The above graph completely satisfies the logic of the rich getting richer and the poor getting
poorer.
Code:
The following code is a part of the function which we will eventually implement using the
networkx library.
639
Chapter 78. Barabasi Albert Graph (for Scale Free Models)
m : int
Number of edges to attach from a new node to existing nodes
seed : int, optional
Seed for random number generator (default=None).
Returns
-------
G : Graph
Raises
------
NetworkXError
If ``m`` does not satisfy ``1 <= m < n``.
if m < 1 or m >=n:
raise nx.NetworkXError("Barabási–Albert network must have m >= 1"
" and m < n, m = %d, n = %d" % (m, n))
if seed is not None:
random.seed(seed)
# Add m initial nodes (m0 in barabasi-speak)
G=empty_graph(m)
G.name="barabasi_albert_graph(%s,%s)"%(n,m)
# Target nodes for new edges
targets=list(range(m))
# List of existing nodes, with nodes repeated once for each adjacent edge
repeated_nodes=[]
# Start adding the other n-m nodes. The first node is m.
source=m
while source<n:
# Add edges to m nodes from the source.
G.add_edges_from(zip(*m,targets))
# Add one node to the list for each new edge just created.
repeated_nodes.extend(targets)
# And the new node "source" has m edges to add to the list.
repeated_nodes.extend(*m)
# Now choose m unique nodes from the existing nodes
# Pick uniformly from repeated_nodes (preferential attachement)
targets = _random_subset(repeated_nodes,m)
source += 1
return G
The above code is a part of the networkx library which is used to handle the random graphs
efficiently in python. One will have to install it before running the following code.
640
Chapter 78. Barabasi Albert Graph (for Scale Free Models)
To display the above graph, I used the matplotlib library. We need to install it before the
execution of the below codes.
Output:
641
Chapter 78. Barabasi Albert Graph (for Scale Free Models)
Source
https://www.geeksforgeeks.org/barabasi-albert-graph-scale-free-models/
642
Chapter 79
643
Chapter 79. Bellman-Ford Algorithm DP-23
have at-most one edge in the path. Then, it calculates shortest paths with at-most 2 edges,
and so on. After the i-th iteration of outer loop, the shortest paths with at most i edges
are calculated. There can be maximum V – 1 edges in any simple path, that is why the
outer loop runs v – 1 times. The idea is, assuming that there is no negative weight cycle,
if we have calculated shortest paths with at most i edges, then an iteration over all edges
guarantees to give shortest path with at-most (i+1) edges (Proof is simple, you can refer
this or MIT Video Lecture)
Example
Let us understand the algorithm with following example graph. The images are taken from
thissource.
Let the given source vertex be 0. Initialize all distances as infinite, except the distance to
source itself. Total number of vertices in the graph is 5, so all edges must be processed 4
times.
Let all edges are processed in following order: (B,E), (D,B), (B,D), (A,B), (A,C), (D,C),
(B,C), (E,D). We get following distances when all edges are processed first time. The first
row in shows initial distances. The second row shows distances when edges (B,E), (D,B),
(B,D) and (A,B) are processed. The third row shows distances when (A,C) is processed.
The fourth row shows when (D,C), (B,C) and (E,D) are processed.
644
Chapter 79. Bellman-Ford Algorithm DP-23
The first iteration guarantees to give all shortest paths which are at most 1 edge long. We
get following distances when all edges are processed second time (The last row shows final
values).
The second iteration guarantees to give all shortest paths which are at most 2 edges long.
The algorithm processes all edges 2 more times. The distances are minimized after the
second iteration, so third and fourth iterations don’t update the distances.
Implementation:
C++
645
Chapter 79. Bellman-Ford Algorithm DP-23
646
Chapter 79. Bellman-Ford Algorithm DP-23
// as INFINITE
for (int i = 0; i < V; i++)
dist[i] = INT_MAX;
dist[src] = 0;
// Step 2: Relax all edges |V| - 1 times. A simple shortest
// path from src to any other vertex can have at-most |V| - 1
// edges
for (int i = 1; i <= V-1; i++)
{
for (int j = 0; j < E; j++)
{
int u = graph->edge[j].src;
int v = graph->edge[j].dest;
int weight = graph->edge[j].weight;
if (dist[u] != INT_MAX && dist[u] + weight < dist[v])
dist[v] = dist[u] + weight;
}
}
// Step 3: check for negative-weight cycles. The above step
// guarantees shortest distances if graph doesn't contain
// negative weight cycle. If we get a shorter path, then there
// is a cycle.
for (int i = 0; i < E; i++)
{
int u = graph->edge[i].src;
int v = graph->edge[i].dest;
int weight = graph->edge[i].weight;
if (dist[u] != INT_MAX && dist[u] + weight < dist[v])
printf("Graph contains negative weight cycle");
}
printArr(dist, V);
return;
}
// Driver program to test above functions
int main()
{
/* Let us create the graph given in above example */
int V = 5; // Number of vertices in graph
int E = 8; // Number of edges in graph
struct Graph* graph = createGraph(V, E);
// add edge 0-1 (or A-B in above figure)
graph->edge[0].src = 0;
647
Chapter 79. Bellman-Ford Algorithm DP-23
graph->edge[0].dest = 1;
graph->edge[0].weight = -1;
// add edge 0-2 (or A-C in above figure)
graph->edge[1].src = 0;
graph->edge[1].dest = 2;
graph->edge[1].weight = 4;
// add edge 1-2 (or B-C in above figure)
graph->edge[2].src = 1;
graph->edge[2].dest = 2;
graph->edge[2].weight = 3;
// add edge 1-3 (or B-D in above figure)
graph->edge[3].src = 1;
graph->edge[3].dest = 3;
graph->edge[3].weight = 2;
// add edge 1-4 (or A-E in above figure)
graph->edge[4].src = 1;
graph->edge[4].dest = 4;
graph->edge[4].weight = 2;
// add edge 3-2 (or D-C in above figure)
graph->edge[5].src = 3;
graph->edge[5].dest = 2;
graph->edge[5].weight = 5;
// add edge 3-1 (or D-B in above figure)
graph->edge[6].src = 3;
graph->edge[6].dest = 1;
graph->edge[6].weight = 1;
// add edge 4-3 (or E-D in above figure)
graph->edge[7].src = 4;
graph->edge[7].dest = 3;
graph->edge[7].weight = -3;
BellmanFord(graph, 0);
return 0;
}
Java
648
Chapter 79. Bellman-Ford Algorithm DP-23
import java.lang.*;
import java.io.*;
// A class to represent a connected, directed and weighted graph
class Graph
{
// A class to represent a weighted edge in graph
class Edge {
int src, dest, weight;
Edge() {
src = dest = weight = 0;
}
};
int V, E;
Edge edge[];
// Creates a graph with V vertices and E edges
Graph(int v, int e)
{
V = v;
E = e;
edge = new Edge[e];
for (int i=0; i<e; ++i)
edge[i] = new Edge();
}
// The main function that finds shortest distances from src
// to all other vertices using Bellman-Ford algorithm. The
// function also detects negative weight cycle
void BellmanFord(Graph graph,int src)
{
int V = graph.V, E = graph.E;
int dist[] = new int[V];
// Step 1: Initialize distances from src to all other
// vertices as INFINITE
for (int i=0; i<V; ++i)
dist[i] = Integer.MAX_VALUE;
dist[src] = 0;
// Step 2: Relax all edges |V| - 1 times. A simple
// shortest path from src to any other vertex can
// have at-most |V| - 1 edges
for (int i=1; i<V; ++i)
{
for (int j=0; j<E; ++j)
{
649
Chapter 79. Bellman-Ford Algorithm DP-23
int u = graph.edge[j].src;
int v = graph.edge[j].dest;
int weight = graph.edge[j].weight;
if (dist[u]!=Integer.MAX_VALUE &&
dist[u]+weight<dist[v])
dist[v]=dist[u]+weight;
}
}
// Step 3: check for negative-weight cycles. The above
// step guarantees shortest distances if graph doesn't
// contain negative weight cycle. If we get a shorter
// path, then there is a cycle.
for (int j=0; j<E; ++j)
{
int u = graph.edge[j].src;
int v = graph.edge[j].dest;
int weight = graph.edge[j].weight;
if (dist[u] != Integer.MAX_VALUE &&
dist[u]+weight < dist[v])
System.out.println("Graph contains negative weight cycle");
}
printArr(dist, V);
}
// A utility function used to print the solution
void printArr(int dist[], int V)
{
System.out.println("Vertex Distance from Source");
for (int i=0; i<V; ++i)
System.out.println(i+"\t\t"+dist[i]);
}
// Driver method to test above function
public static void main(String[] args)
{
int V = 5; // Number of vertices in graph
int E = 8; // Number of edges in graph
Graph graph = new Graph(V, E);
// add edge 0-1 (or A-B in above figure)
graph.edge[0].src = 0;
graph.edge[0].dest = 1;
graph.edge[0].weight = -1;
// add edge 0-2 (or A-C in above figure)
graph.edge[1].src = 0;
650
Chapter 79. Bellman-Ford Algorithm DP-23
graph.edge[1].dest = 2;
graph.edge[1].weight = 4;
// add edge 1-2 (or B-C in above figure)
graph.edge[2].src = 1;
graph.edge[2].dest = 2;
graph.edge[2].weight = 3;
// add edge 1-3 (or B-D in above figure)
graph.edge[3].src = 1;
graph.edge[3].dest = 3;
graph.edge[3].weight = 2;
// add edge 1-4 (or A-E in above figure)
graph.edge[4].src = 1;
graph.edge[4].dest = 4;
graph.edge[4].weight = 2;
// add edge 3-2 (or D-C in above figure)
graph.edge[5].src = 3;
graph.edge[5].dest = 2;
graph.edge[5].weight = 5;
// add edge 3-1 (or D-B in above figure)
graph.edge[6].src = 3;
graph.edge[6].dest = 1;
graph.edge[6].weight = 1;
// add edge 4-3 (or E-D in above figure)
graph.edge[7].src = 4;
graph.edge[7].dest = 3;
graph.edge[7].weight = -3;
graph.BellmanFord(graph, 0);
}
}
// Contributed by Aakash Hasija
Python
651
Chapter 79. Bellman-Ford Algorithm DP-23
def __init__(self,vertices):
self.V= vertices #No. of vertices
self.graph = [] # default dictionary to store graph
# function to add an edge to graph
def addEdge(self,u,v,w):
self.graph.append([u, v, w])
# utility function used to print the solution
def printArr(self, dist):
print("Vertex Distance from Source")
for i in range(self.V):
print("%d \t\t %d" % (i, dist[i]))
# The main function that finds shortest distances from src to
# all other vertices using Bellman-Ford algorithm. The function
# also detects negative weight cycle
def BellmanFord(self, src):
# Step 1: Initialize distances from src to all other vertices
# as INFINITE
dist = [float("Inf")] * self.V
dist[src] = 0
# Step 2: Relax all edges |V| - 1 times. A simple shortest
# path from src to any other vertex can have at-most |V| - 1
# edges
for i in range(self.V - 1):
# Update dist value and parent index of the adjacent vertices of
# the picked vertex. Consider only those vertices which are still in
# queue
for u, v, w in self.graph:
if dist[u] != float("Inf") and dist[u] + w < dist[v]:
dist[v] = dist[u] + w
# Step 3: check for negative-weight cycles. The above step
# guarantees shortest distances if graph doesn't contain
# negative weight cycle. If we get a shorter path, then there
# is a cycle.
for u, v, w in self.graph:
if dist[u] != float("Inf") and dist[u] + w < dist[v]:
print "Graph contains negative weight cycle"
return
# print all distance
self.printArr(dist)
652
Chapter 79. Bellman-Ford Algorithm DP-23
g = Graph(5)
g.addEdge(0, 1, -1)
g.addEdge(0, 2, 4)
g.addEdge(1, 2, 3)
g.addEdge(1, 3, 2)
g.addEdge(1, 4, 2)
g.addEdge(3, 2, 5)
g.addEdge(3, 1, 1)
g.addEdge(4, 3, -3)
#Print the solution
g.BellmanFord(0)
#This code is contributed by Neelam Yadav
Output:
Notes
1) Negative weights are found in various applications of graphs. For example, instead of
paying cost for a path, we may get some advantage if we follow the path.
2) Bellman-Ford works better (better than Dijksra’s) for distributed systems. Unlike Di-
jksra’s where we need to find minimum value of all vertices, in Bellman-Ford, edges are
considered one by one.
Exercise
1) The standard Bellman-Ford algorithm reports shortest path only if there is no negative
weight cycles. Modify it so that it reports minimum distances even if there is a negative
weight cycle.
2) Can we use Dijksra’s algorithm for shortest paths for graphs with negative weights – one
idea can be, calculate the minimum weight value, add a positive value (equal to absolute
value of minimum weight value) to all weights and run the Dijksra’s algorithm for the
modified graph. Will this algorithm work?
References:
http://www.youtube.com/watch?v=Ttezuzs39nk
http://en.wikipedia.org/wiki/Bellman%E2%80%93Ford_algorithm
http://www.cs.arizona.edu/classes/cs445/spring07/ShortestPath2.prn.pdf
653
Chapter 79. Bellman-Ford Algorithm DP-23
Source
https://www.geeksforgeeks.org/bellman-ford-algorithm-dp-23/
654
Chapter 80
655
Chapter 80. Best First Search (Informed Search)
pq.insert(v)
Mark v "Examined"
End procedure
pq initially contains S
We remove s from and process unvisited
neighbors of S to pq.
pq now contains {A, C, B} (C is put
656
Chapter 80. Best First Search (Informed Search)
Analysis :
• The worst case time complexity for Best First Search is O(n * Log n) where n is
number of nodes. In worst case, we may have to visit all nodes before we reach goal.
Note that priority queue is implemented using Min(or Max) Heap, and insert and
remove operations take O(log n) time.
• Performance of the algorithm depends on how well the cost or evaluation function is
designed.
Related Article:
A* Search Algorithm
Source
https://www.geeksforgeeks.org/best-first-search-informed-search/
657
Chapter 81
Betweenness Centrality
(Centrality Measure)
where is the total number of shortest paths from node to node and is
the number of those paths that pass through .
Note that the betweenness centrality of a node scales with the number of pairs of
nodes as implied by the summation indices. Therefore, the calculation may be
rescaled by dividing through by the number of pairs of nodes not including , so
658
Chapter 81. Betweenness Centrality (Centrality Measure)
Note that this will always be a scaling from a smaller range into a larger range, so no
precision is lost.
Weighted Networks
In a weighted network the links connecting the nodes are no longer treated as binary inter-
actions, but are weighted in proportion to their capacity, influence, frequency, etc., which
adds another dimension of heterogeneity within the network beyond the topological effects.
A node’s strength in a weighted network is given by the sum of the weights of its adjacent
edges.
With and being adjacency and weight matrices between nodes and , respec-
tively. Analogous to the power law distribution of degree found in scale free networks, the
strength of a given node follows a power law distribution as well.
A study of the average value of the strength for vertices with betweenness shows
that the functional behavior can be approximated by a scaling form
Following is the code for the calculation of the betweenness centrality of the graph and its
various nodes.
659
Chapter 81. Betweenness Centrality (Centrality Measure)
c_B(v) =\sum_{s,t \in V} \frac{\sigma(s, t|v)}{\sigma(s, t)}
where $V$ is the set of nodes, $\sigma(s, t)$ is the number of
shortest $(s, t)$-paths, and $\sigma(s, t|v)$ is the number of
those paths passing through some node $v$ other than $s, t$.
If $s = t$, $\sigma(s, t) = 1$, and if $v \in {s, t}$,
$\sigma(s, t|v) = 0$ [2]_.
Parameters
----------
G : graph
A NetworkX graph.
k : int, optional (default=None)
If k is not None use k node samples to estimate betweenness.
The value of k <= n where n is the number of nodes in the graph.
Higher values give better approximation.
normalized : bool, optional
If True the betweenness values are normalized by `2/((n-1)(n-2))`
for graphs, and `1/((n-1)(n-2))` for directed graphs where `n`
is the number of nodes in G.
weight : None or string, optional (default=None)
If None, all edge weights are considered equal.
Otherwise holds the name of the edge attribute used as weight.
endpoints : bool, optional
If True include the endpoints in the shortest path counts.
Returns
-------
nodes : dictionary
Dictionary of nodes with betweenness centrality as the value.
Notes
-----
The algorithm is from Ulrik Brandes [1]_.
See [4]_ for the original first published version and [2]_ for details on
algorithms for variations and related metrics.
For approximate betweenness calculations set k=#samples to use
k nodes ("pivots") to estimate the betweenness values. For an estimate
of the number of pivots needed see [3]_.
For weighted graphs the edge weights must be greater than zero.
660
Chapter 81. Betweenness Centrality (Centrality Measure)
The above function is invoked using the networkx library and once the library is installed,
you can eventually use it and the following code has to be written in python for the imple-
mentation of the betweenness centrality of a node.
661
Chapter 81. Betweenness Centrality (Centrality Measure)
The above result is a dictionary depicting the value of betweenness centrality of each node.
The above is an extension of my article series on the centrality measures. Keep networking!!!
References
You can read more about the same at
https://en.wikipedia.org/wiki/Betweenness_centrality
http://networkx.readthedocs.io/en/networkx-1.10/index.html
.
Source
https://www.geeksforgeeks.org/betweenness-centrality-centrality-measure/
662
Chapter 82
All vertices are reachable. So, for above graph simple BFS will work.
As in above graph a vertex 1 is unreachable from all vertex, so simple BFS wouldn’t work
for it.
663
Chapter 82. BFS for Disconnected Graph
664
Chapter 82. BFS for Disconnected Graph
}
}
// This function does BFSUtil() for all
// unvisited vertices.
void BFS(vector<int> adj[], int V)
{
vector<bool> visited(V, false);
for (int u=0; u<V; u++)
if (visited[u] == false)
BFSUtil(u, adj, visited);
}
// Driver code
int main()
{
int V = 5;
vector<int> adj[V];
addEdge(adj, 0, 4);
addEdge(adj, 1, 2);
addEdge(adj, 1, 3);
addEdge(adj, 1, 4);
addEdge(adj, 2, 3);
addEdge(adj, 3, 4);
BFS(adj, V);
return 0;
}
Output:
0 4 1 2 3
Source
https://www.geeksforgeeks.org/bfs-disconnected-graph/
665
Chapter 83
Below is an example BFS starting from source vertex 1. Note that there can be multple
BFSs possible for a graph (even from a particular vertex).
666
Chapter 83. BFS using STL for competitive coding
667
Chapter 83. BFS using STL for competitive coding
int f = q.front();
q.pop();
cout << f << " ";
// Enqueue all adjacent of f and mark them visited
for (auto i = g[f].begin(); i != g[f].end(); i++) {
if (!v[*i]) {
q.push(*i);
v[*i] = true;
}
}
}
}
// Driver code
int main()
{
int n, e;
cin >> n >> e;
v.assign(n, false);
g.assign(n, vector<int>());
int a, b;
for (int i = 0; i < e; i++) {
cin >> a >> b;
edge(a, b);
}
for (int i = 0; i < n; i++) {
if (!v[i])
bfs(i);
}
return 0;
}
Input:
8 10
0 1
0 2
0 3
0 4
1 5
2 5
3 6
668
Chapter 83. BFS using STL for competitive coding
4 6
5 7
6 7
Output:
0 1 2 3 4 5 6 7
Source
https://www.geeksforgeeks.org/bfs-using-stl-competitive-coding/
669
Chapter 84
BFS using vectors & queue as per the algorithm of CLRS - GeeksforGeeks
Breadth-first searchtraversal of a graph using the algorithm given in CLRS book.
BFS is one of the ways to traverse a graph. It is named so because it expands the frontier
between discovered and undiscovered vertices uniformly across the breadth of the frontier.
What it means is that the algorithm first discovers all the vertices connected to “u” at a
distance of k before discovering the vertices at a distance of k+1 from u. The algorithm
given in CLRS uses the concept of “colour” to check if a vertex is discovered fully or partially
or undiscovered. It also keeps a track of the distance a vertex u is from the source s.
BFS(G,s)
1 for each vertex u in G.V - {s}
2 u.color = white
3 u.d = INF
4 u.p = NIL
5 s.color = green
6 s.d = 0
7 s.p = NIL
8 Q = NULL
9 ENQUEUE(Q,s)
10 while Q != NULL
11 u = DEQUEUE(Q)
12 for each v in G.Adj[u]
13 if v.color == white
14 v.color = green
15 v.d = u.d + 1
16 v.p = u
17 ENQUEUE(Q,v)
670
Chapter 84. BFS using vectors & queue as per the algorithm of CLRS
18 u.color = dark_green
It produces a “breadth-first tree” with root s that contains all reachable vertices. Let’s take
a simple directed graph and see how BFS traverses it.
The graph
671
Chapter 84. BFS using vectors & queue as per the algorithm of CLRS
Starting of traversal
1st traversal
672
Chapter 84. BFS using vectors & queue as per the algorithm of CLRS
673
Chapter 84. BFS using vectors & queue as per the algorithm of CLRS
/* Now the node u is completely traversed
and colour is changed to black. */
colour[u] = "dark_green";
}
}
void BFSFull(vector <int> g[], int n)
{
/* Initially all nodes are not traversed.
Therefore, the colour is white. */
colour.assign(n, "white");
d.assign(n, 0);
p.assign(n, -1);
// Calling BFSSingleSource() for all white
// vertices.
for (int i = 0; i < n; i++)
if (colour[i] == "white")
BFSSingleSource(g, i);
}
// Driver Function
int main()
{
// Graph with 7 nodes and 6 edges.
int n = 7;
// The Graph vector
vector <int> g[n];
addEdge(g, 0, 1);
addEdge(g, 0, 2);
addEdge(g, 1, 3);
addEdge(g, 1, 4);
addEdge(g, 2, 5);
addEdge(g, 2, 6);
BFSFull(g, n);
return 0;
}
Output:
0 1 2 3 4 5 6
674
Chapter 84. BFS using vectors & queue as per the algorithm of CLRS
Source
https://www.geeksforgeeks.org/bfs-using-vectors-queue-per-algorithm-clrs/
675
Chapter 85
Bidirectional Search
Bidirectional search replaces single search graph(which is likely to grow exponentially) with
two smaller sub graphs – one starting from initial vertex and other starting from goal vertex.
The search terminates when two graphs intersect.
Just like A* algorithm, bidirectional search can be guided by a heuristic estimate of remain-
ing distance from source to goal and vice versa for finding shortest path possible.
Consider following simple example-
676
Chapter 85. Bidirectional Search
Suppose we want to find if there exists a path from vertex 0 to vertex 14. Here we can
execute two searches, one from vertex 0 and other from vertex 14. When both forward and
backward search meet at vertex 7, we know that we have found a path from node 0 to 14
and search can be terminated now. We can clearly see that we have successfully avoided
unnecessary exploration.
Why bidirectional approach?
Because in many cases it is faster, it dramatically reduce the amount of required exploration.
Suppose if branching factor of tree is b and distance of goal vertex from source is d, then
execute two search operation then the complexity would be for each search
1. Both initial and goal states are unique and completely defined.
Performance measures
677
Chapter 85. Bidirectional Search
• Optimality : It is optimal if BFS is used for search and paths have uniform cost.
Below is very simple implementation representing the concept of bidirectional search using
BFS. This implementation considers undirected paths without any weight.
678
Chapter 85. Bidirectional Search
{
int current = queue->front();
queue->pop_front();
list<int>::iterator i;
for (i=adj[current].begin();i != adj[current].end();i++)
{
// If adjacent vertex is not visited earlier
// mark it visited by assigning true value
if (!visited[*i])
{
// set current as parent of this vertex
parent[*i] = current;
// Mark this vertex visited
visited[*i] = true;
// Push to the end of queue
queue->push_back(*i);
}
}
};
// check for intersecting vertex
int Graph::isIntersecting(bool *s_visited, bool *t_visited)
{
int intersectNode = -1;
for(int i=0;i<V;i++)
{
// if a vertex is visited by both front
// and back BFS search return that node
// else return -1
if(s_visited[i] && t_visited[i])
return i;
}
return -1;
};
// Print the path from source to target
void Graph::printPath(int *s_parent, int *t_parent,
int s, int t, int intersectNode)
{
vector<int> path;
path.push_back(intersectNode);
int i = intersectNode;
while (i != s)
{
path.push_back(s_parent[i]);
i = s_parent[i];
679
Chapter 85. Bidirectional Search
}
reverse(path.begin(), path.end());
i = intersectNode;
while(i != t)
{
path.push_back(t_parent[i]);
i = t_parent[i];
}
vector<int>::iterator it;
cout<<"*****Path*****\n";
for(it = path.begin();it != path.end();it++)
cout<<*it<<" ";
cout<<"\n";
};
// Method for bidirectional searching
int Graph::biDirSearch(int s, int t)
{
// boolean array for BFS started from
// source and target(front and backward BFS)
// for keeping track on visited nodes
bool s_visited[V], t_visited[V];
// Keep track on parents of nodes
// for front and backward search
int s_parent[V], t_parent[V];
// queue for front and backward search
list<int> s_queue, t_queue;
int intersectNode = -1;
// necessary initialization
for(int i=0; i<V; i++)
{
s_visited[i] = false;
t_visited[i] = false;
}
s_queue.push_back(s);
s_visited[s] = true;
// parent of source is set to -1
s_parent[s]=-1;
t_queue.push_back(t);
t_visited[t] = true;
680
Chapter 85. Bidirectional Search
// parent of target is set to -1
t_parent[t] = -1;
while (!s_queue.empty() && !t_queue.empty())
{
// Do BFS from source and target vertices
BFS(&s_queue, s_visited, s_parent);
BFS(&t_queue, t_visited, t_parent);
// check for intersecting vertex
intersectNode = isIntersecting(s_visited, t_visited);
// If intersecting vertex is found
// that means there exist a path
if(intersectNode != -1)
{
cout << "Path exist between " << s << " and "
<< t << "\n";
cout << "Intersection at: " << intersectNode << "\n";
// print the path and exit the program
printPath(s_parent, t_parent, s, t, intersectNode);
exit(0);
}
}
return -1;
}
// Driver code
int main()
{
// no of vertices in graph
int n=15;
// source vertex
int s=0;
// target vertex
int t=14;
// create a graph given in above diagram
Graph g(n);
g.addEdge(0, 4);
g.addEdge(1, 4);
g.addEdge(2, 5);
g.addEdge(3, 5);
g.addEdge(4, 6);
681
Chapter 85. Bidirectional Search
g.addEdge(5, 6);
g.addEdge(6, 7);
g.addEdge(7, 8);
g.addEdge(8, 9);
g.addEdge(8, 10);
g.addEdge(9, 11);
g.addEdge(9, 12);
g.addEdge(10, 13);
g.addEdge(10, 14);
if (g.biDirSearch(s, t) == -1)
cout << "Path don't exist between "
<< s << " and " << t << "\n";
return 0;
}
Output:
References
• https://en.wikipedia.org/wiki/Bidirectional_search
Source
https://www.geeksforgeeks.org/bidirectional-search/
682
Chapter 86
683
Chapter 86. Boggle (Find all possible words in a board of characters) Set 1
The idea is to consider every character as a starting character and find all words starting
with it. All words starting from a character can be found using Depth First Traversal. We
do depth first traversal starting from every cell. We keep track of visited cells to make sure
that a cell is considered only once in a word.
684
Chapter 86. Boggle (Find all possible words in a board of characters) Set 1
685
Chapter 86. Boggle (Find all possible words in a board of characters) Set 1
Output:
Note that the above solution may print the same word multiple times. For example, if
we add “SEEK” to the dictionary, it is printed multiple times. To avoid this, we can use
hashing to keep track of all printed words.
In below set 2, we have discussed Trie based optimized solution:
Boggle Set 2 (Using Trie)
This article is contributed by Rishabh. Please write comments if you find anything incor-
rect, or you want to share more information about the topic discussed above.
Source
https://www.geeksforgeeks.org/boggle-find-possible-words-board-characters/
686
Chapter 87
687
Chapter 87. Boggle Set 2 (Using Trie)
2. After that we have pick only those character in boggle[][] which are child of root of Trie
Let for above we pick ‘G’ boggle[0][0] , ‘Q’ boggle[2][0] (they both are present in boggle
matrix)
3. search a word in a trie which start with character that we pick in step 2
688
Chapter 87. Boggle Set 2 (Using Trie)
if root->leaf == true
print word
689
Chapter 87. Boggle Set 2 (Using Trie)
690
Chapter 87. Boggle Set 2 (Using Trie)
visited[i][j] = true;
// traverse all childs of current root
for (int K =0; K < SIZE; K++)
{
if (root->Child[K] != NULL)
{
// current character
char ch = (char)K + (char)'A' ;
// Recursively search reaming character of word
// in trie for all 8 adjacent cells of boggle[i][j]
if (isSafe(i+1,j+1,visited) && boggle[i+1][j+1] == ch)
searchWord(root->Child[K],boggle,i+1,j+1,visited,str+ch);
if (isSafe(i, j+1,visited) && boggle[i][j+1] == ch)
searchWord(root->Child[K],boggle,i, j+1,visited,str+ch);
if (isSafe(i-1,j+1,visited) && boggle[i-1][j+1] == ch)
searchWord(root->Child[K],boggle,i-1, j+1,visited,str+ch);
if (isSafe(i+1,j, visited) && boggle[i+1][j] == ch)
searchWord(root->Child[K],boggle,i+1, j,visited,str+ch);
if (isSafe(i+1,j-1,visited) && boggle[i+1][j-1] == ch)
searchWord(root->Child[K],boggle,i+1, j-1,visited,str+ch);
if (isSafe(i, j-1,visited)&& boggle[i][j-1] == ch)
searchWord(root->Child[K],boggle,i,j-1,visited,str+ch);
if (isSafe(i-1,j-1,visited) && boggle[i-1][j-1] == ch)
searchWord(root->Child[K],boggle,i-1, j-1,visited,str+ch);
if (isSafe(i-1, j,visited) && boggle[i-1][j] == ch)
searchWord(root->Child[K],boggle,i-1, j, visited,str+ch);
}
}
// make current element unvisited
visited[i][j] = false;
}
}
// Prints all words present in dictionary.
void findWords(char boggle[M][N], TrieNode *root)
{
// Mark all characters as not visited
bool visited[M][N];
memset(visited,false,sizeof(visited));
TrieNode *pChild = root ;
string str = "";
// traverse all matrix elements
691
Chapter 87. Boggle Set 2 (Using Trie)
Java
692
Chapter 87. Boggle Set 2 (Using Trie)
693
Chapter 87. Boggle Set 2 (Using Trie)
694
Chapter 87. Boggle Set 2 (Using Trie)
searchWord(root.Child[K],boggle,i+1, j-1,
visited,str+ch);
if (isSafe(i, j-1,visited)&& boggle[i][j-1]
== ch)
searchWord(root.Child[K],boggle,i,j-1,
visited,str+ch);
if (isSafe(i-1,j-1,visited) && boggle[i-1][j-1]
== ch)
searchWord(root.Child[K],boggle,i-1, j-1,
visited,str+ch);
if (isSafe(i-1, j,visited) && boggle[i-1][j]
== ch)
searchWord(root.Child[K],boggle,i-1, j,
visited,str+ch);
}
}
// make current element unvisited
visited[i][j] = false;
}
}
// Prints all words present in dictionary.
static void findWords(char boggle[][], TrieNode root)
{
// Mark all characters as not visited
boolean[][] visited = new boolean[M][N];
TrieNode pChild = root ;
String str = "";
// traverse all matrix elements
for (int i = 0 ; i < M; i++)
{
for (int j = 0 ; j < N ; j++)
{
// we start searching for word in dictionary
// if we found a character which is child
// of Trie root
if (pChild.Child[(boggle[i][j]) - 'A'] != null)
{
str = str+boggle[i][j];
searchWord(pChild.Child[(boggle[i][j]) - 'A'],
boggle, i, j, visited, str);
str = "";
}
}
}
695
Chapter 87. Boggle Set 2 (Using Trie)
}
// Driver program to test above function
public static void main(String args[])
{
// Let the given dictionary be following
String dictionary[] = {"GEEKS", "FOR", "QUIZ", "GEE"};
// root Node of trie
TrieNode root = new TrieNode();
// insert all words of dictionary into trie
int n = dictionary.length;
for (int i=0; i<n; i++)
insert(root, dictionary[i]);
char boggle[][] = {{'G','I','Z'},
{'U','E','K'},
{'Q','S','E'}
};
findWords(boggle, root);
}
}
// This code is contributed by Sumit Ghosh
Output:
Source
https://www.geeksforgeeks.org/boggle-set-2-using-trie/
696
Chapter 88
Source
https://www.geeksforgeeks.org/g-fact-83/
697
Chapter 89
Below is the idea behind above algorithm (The idea is same as Prim’s MST algorithm).
A spanning tree means all vertices must be connected. So the two disjoint subsets (discussed
above) of vertices must be connected to make a Spanning Tree. And they must be connected
with the minimum weight edge to make it a Minimum Spanning Tree.
Let us understand the algorithm with below example.
698
Chapter 89. Boruvka’s algorithm Greedy Algo-9
Initially MST is empty. Every vertex is singe component as highlighted in blue color in
below diagram.
For every component, find the cheapest edge that connects it to some other component.
The cheapest edges are highlighted with green color. Now MST becomes {0-1, 2-8, 2-3, 3-4,
5-6, 6-7}.
699
Chapter 89. Boruvka’s algorithm Greedy Algo-9
After above step, components are {{0,1}, {2,3,4,8}, {5,6,7}}. The components are encircled
with blue color.
We again repeat the step, i.e., for every component, find the cheapest edge that connects it
to some other component.
The cheapest edges are highlighted with green color. Now MST becomes {0-1, 2-8, 2-3, 3-4,
5-6, 6-7, 1-2, 2-5}
At this stage, there is only one component {0, 1, 2, 3, 4, 5, 6, 7, 8} which has all edges.
Since there is only one component left, we stop and return MST.
Implementation:
Below is implementation of above algorithm. The input graph is represented as a collection
of edges and union-find data structure is used to keep track of components.
C/C++
700
Chapter 89. Boruvka’s algorithm Greedy Algo-9
struct Edge
{
int src, dest, weight;
};
// a structure to represent a connected, undirected
// and weighted graph as a collection of edges.
struct Graph
{
// V-> Number of vertices, E-> Number of edges
int V, E;
// graph is represented as an array of edges.
// Since the graph is undirected, the edge
// from src to dest is also edge from dest
// to src. Both are counted as 1 edge here.
Edge* edge;
};
// A structure to represent a subset for union-find
struct subset
{
int parent;
int rank;
};
// Function prototypes for union-find (These functions are defined
// after boruvkaMST() )
int find(struct subset subsets[], int i);
void Union(struct subset subsets[], int x, int y);
// The main function for MST using Boruvka's algorithm
void boruvkaMST(struct Graph* graph)
{
// Get data of given graph
int V = graph->V, E = graph->E;
Edge *edge = graph->edge;
// Allocate memory for creating V subsets.
struct subset *subsets = new subset[V];
// An array to store index of the cheapest edge of
// subset. The stored index for indexing array 'edge[]'
int *cheapest = new int[V];
// Create V subsets with single elements
for (int v = 0; v < V; ++v)
{
701
Chapter 89. Boruvka’s algorithm Greedy Algo-9
subsets[v].parent = v;
subsets[v].rank = 0;
cheapest[v] = -1;
}
// Initially there are V different trees.
// Finally there will be one tree that will be MST
int numTrees = V;
int MSTweight = 0;
// Keep combining components (or sets) until all
// compnentes are not combined into single MST.
while (numTrees > 1)
{
// Everytime initialize cheapest array
for (int v = 0; v < V; ++v)
{
cheapest[v] = -1;
}
// Traverse through all edges and update
// cheapest of every component
for (int i=0; i<E; i++)
{
// Find components (or sets) of two corners
// of current edge
int set1 = find(subsets, edge[i].src);
int set2 = find(subsets, edge[i].dest);
// If two corners of current edge belong to
// same set, ignore current edge
if (set1 == set2)
continue;
// Else check if current edge is closer to previous
// cheapest edges of set1 and set2
else
{
if (cheapest[set1] == -1 ||
edge[cheapest[set1]].weight > edge[i].weight)
cheapest[set1] = i;
if (cheapest[set2] == -1 ||
edge[cheapest[set2]].weight > edge[i].weight)
cheapest[set2] = i;
}
}
702
Chapter 89. Boruvka’s algorithm Greedy Algo-9
// Consider the above picked cheapest edges and add them
// to MST
for (int i=0; i<V; i++)
{
// Check if cheapest for current set exists
if (cheapest[i] != -1)
{
int set1 = find(subsets, edge[cheapest[i]].src);
int set2 = find(subsets, edge[cheapest[i]].dest);
if (set1 == set2)
continue;
MSTweight += edge[cheapest[i]].weight;
printf("Edge %d-%d included in MST\n",
edge[cheapest[i]].src, edge[cheapest[i]].dest);
// Do a union of set1 and set2 and decrease number
// of trees
Union(subsets, set1, set2);
numTrees--;
}
}
}
printf("Weight of MST is %d\n", MSTweight);
return;
}
// Creates a graph with V vertices and E edges
struct Graph* createGraph(int V, int E)
{
Graph* graph = new Graph;
graph->V = V;
graph->E = E;
graph->edge = new Edge[E];
return graph;
}
// A utility function to find set of an element i
// (uses path compression technique)
int find(struct subset subsets[], int i)
{
// find root and make root as parent of i
// (path compression)
if (subsets[i].parent != i)
subsets[i].parent =
find(subsets, subsets[i].parent);
703
Chapter 89. Boruvka’s algorithm Greedy Algo-9
return subsets[i].parent;
}
// A function that does union of two sets of x and y
// (uses union by rank)
void Union(struct subset subsets[], int x, int y)
{
int xroot = find(subsets, x);
int yroot = find(subsets, y);
// Attach smaller rank tree under root of high
// rank tree (Union by Rank)
if (subsets[xroot].rank < subsets[yroot].rank)
subsets[xroot].parent = yroot;
else if (subsets[xroot].rank > subsets[yroot].rank)
subsets[yroot].parent = xroot;
// If ranks are same, then make one as root and
// increment its rank by one
else
{
subsets[yroot].parent = xroot;
subsets[xroot].rank++;
}
}
// Driver program to test above functions
int main()
{
/* Let us create following weighted graph
10
0--------1
| \ |
6| 5\ |15
| \ |
2--------3
4 */
int V = 4; // Number of vertices in graph
int E = 5; // Number of edges in graph
struct Graph* graph = createGraph(V, E);
// add edge 0-1
graph->edge[0].src = 0;
graph->edge[0].dest = 1;
graph->edge[0].weight = 10;
// add edge 0-2
704
Chapter 89. Boruvka’s algorithm Greedy Algo-9
graph->edge[1].src = 0;
graph->edge[1].dest = 2;
graph->edge[1].weight = 6;
// add edge 0-3
graph->edge[2].src = 0;
graph->edge[2].dest = 3;
graph->edge[2].weight = 5;
// add edge 1-3
graph->edge[3].src = 1;
graph->edge[3].dest = 3;
graph->edge[3].weight = 15;
// add edge 2-3
graph->edge[4].src = 2;
graph->edge[4].dest = 3;
graph->edge[4].weight = 4;
boruvkaMST(graph);
return 0;
}
// Thanks to Anukul Chand for modifying above code.
Python
705
Chapter 89. Boruvka’s algorithm Greedy Algo-9
if parent[i] == i:
return i
return self.find(parent, parent[i])
# A function that does union of two sets of x and y
# (uses union by rank)
def union(self, parent, rank, x, y):
xroot = self.find(parent, x)
yroot = self.find(parent, y)
# Attach smaller rank tree under root of high rank tree
# (Union by Rank)
if rank[xroot] < rank[yroot]:
parent[xroot] = yroot
elif rank[xroot] > rank[yroot]:
parent[yroot] = xroot
#If ranks are same, then make one as root and increment
# its rank by one
else :
parent[yroot] = xroot
rank[xroot] += 1
# The main function to construct MST using Kruskal's algorithm
def boruvkaMST(self):
parent = []; rank = [];
# An array to store index of the cheapest edge of
# subset. It store [u,v,w] for each component
cheapest =[]
# Initially there are V different trees.
# Finally there will be one tree that will be MST
numTrees = self.V
MSTweight = 0
# Create V subsets with single elements
for node in range(self.V):
parent.append(node)
rank.append(0)
cheapest =[-1] * self.V
# Keep combining components (or sets) until all
# compnentes are not combined into single MST
while numTrees > 1:
# Traverse through all edges and update
# cheapest of every component
706
Chapter 89. Boruvka’s algorithm Greedy Algo-9
for i in range(len(self.graph)):
# Find components (or sets) of two corners
# of current edge
u,v,w = self.graph[i]
set1 = self.find(parent, u)
set2 = self.find(parent ,v)
# If two corners of current edge belong to
# same set, ignore current edge. Else check if
# current edge is closer to previous
# cheapest edges of set1 and set2
if set1 != set2:
if cheapest[set1] == -1 or cheapest[set1][2] > w :
cheapest[set1] = [u,v,w]
if cheapest[set2] == -1 or cheapest[set2][2] > w :
cheapest[set2] = [u,v,w]
# Consider the above picked cheapest edges and add them
# to MST
for node in range(self.V):
#Check if cheapest for current set exists
if cheapest[node] != -1:
u,v,w = cheapest[node]
set1 = self.find(parent, u)
set2 = self.find(parent ,v)
if set1 != set2 :
MSTweight += w
self.union(parent, rank, set1, set2)
print ("Edge %d-%d with weight %d included in MST" % (u,v,w))
numTrees = numTrees - 1
#reset cheapest array
cheapest =[-1] * self.V
print ("Weight of MST is %d" % MSTweight)
g = Graph(4)
g.addEdge(0, 1, 10)
g.addEdge(0, 2, 6)
g.addEdge(0, 3, 5)
707
Chapter 89. Boruvka’s algorithm Greedy Algo-9
g.addEdge(1, 3, 15)
g.addEdge(2, 3, 4)
g.boruvkaMST()
#This code is contributed by Neelam Yadav
Output:
Source
https://www.geeksforgeeks.org/boruvkas-algorithm-greedy-algo-9/
708
Chapter 90
Following are the implementations of simple Breadth First Traversal from a given source.
The implementation uses adjacency list representation of graphs. STL‘s list container is
used to store lists of adjacent nodes and queue of nodes needed for BFS traversal.
C++
709
Chapter 90. Breadth First Search or BFS for a Graph
#include<iostream>
#include <list>
using namespace std;
// This class represents a directed graph using
// adjacency list representation
class Graph
{
int V; // No. of vertices
// Pointer to an array containing adjacency
// lists
list<int> *adj;
public:
Graph(int V); // Constructor
// function to add an edge to graph
void addEdge(int v, int w);
// prints BFS traversal from a given source s
void BFS(int s);
};
Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V];
}
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w); // Add w to v’s list.
}
void Graph::BFS(int s)
{
// Mark all the vertices as not visited
bool *visited = new bool[V];
for(int i = 0; i < V; i++)
visited[i] = false;
// Create a queue for BFS
list<int> queue;
// Mark the current node as visited and enqueue it
visited[s] = true;
queue.push_back(s);
710
Chapter 90. Breadth First Search or BFS for a Graph
// 'i' will be used to get all adjacent
// vertices of a vertex
list<int>::iterator i;
while(!queue.empty())
{
// Dequeue a vertex from queue and print it
s = queue.front();
cout << s << " ";
queue.pop_front();
// Get all adjacent vertices of the dequeued
// vertex s. If a adjacent has not been visited,
// then mark it visited and enqueue it
for (i = adj[s].begin(); i != adj[s].end(); ++i)
{
if (!visited[*i])
{
visited[*i] = true;
queue.push_back(*i);
}
}
}
}
// Driver program to test methods of graph class
int main()
{
// Create a graph given in the above diagram
Graph g(4);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 2);
g.addEdge(2, 0);
g.addEdge(2, 3);
g.addEdge(3, 3);
cout << "Following is Breadth First Traversal "
<< "(starting from vertex 2) \n";
g.BFS(2);
return 0;
}
Java
711
Chapter 90. Breadth First Search or BFS for a Graph
712
Chapter 90. Breadth First Search or BFS for a Graph
Python3
713
Chapter 90. Breadth First Search or BFS for a Graph
714
Chapter 90. Breadth First Search or BFS for a Graph
print ("Following is Breadth First Traversal"
" (starting from vertex 2)")
g.BFS(2)
# This code is contributed by Neelam Yadav
Output:
Illustration :
715
Chapter 90. Breadth First Search or BFS for a Graph
716
Chapter 90. Breadth First Search or BFS for a Graph
Note that the above code traverses only the vertices reachable from a given source vertex.
All the vertices may not be reachable from a given vertex (example Disconnected graph).
To print all the vertices, we can modify the BFS function to do traversal starting from all
nodes one by one (Like the DFS modified version) .
Time Complexity: O(V+E) where V is number of vertices in the graph and E is number of
edges in the graph.
You may like to see below also :
717
Chapter 90. Breadth First Search or BFS for a Graph
Source
https://www.geeksforgeeks.org/breadth-first-search-or-bfs-for-a-graph/
718
Chapter 91
Calculate number of nodes between two vertices in an acyclic Graph by Disjoint Union
method - GeeksforGeeks
Given a connected acyclic graph and a source vertex and a destination vertex, your task is to
count the number of vertices between the given source and destination vertex by Disjoint
Union Method .
Examples:
Input : 1 4
4 5
4 2
2 6
6 3
1 3
Output : 3
In the input 6 is the total number of vertices
labeled from 1 to 6 and next 5 lines are connection
between verticies . Please see the figure for more
explanation. And in last line 1 is the source vertex
and 3 is the destination vertex. From the figure
it is clear that there are 3 nodes(4, 2, 6) present
between 1 and 3 .
719
Chapter 91. Calculate number of nodes between two vertices in an acyclic Graph by
Disjoint Union method
To use disjoint union method we have to first check the parent of each of the node of the
given graph. We can use BFS to traverse through the graph and calculate the parent vertex
of each vertices of graph. For example, if we traverse the graph (i.e starts our bfs) from
vertex 1 then 1 is the parent of 4 , then 4 is the parent of 5 and 2 , again 2 is the parent of
6 and 6 is the parent of 3 .
Now to calculate number of nodes between the source node and destination node, we have
to make a loop that starts with parent of destination node and after every iteratition we will
update this node with parent of current node , keeping the count of number of iterations.
The execution of loop will terminate when we reach the source vertex and the count variable
gives the number of nodes in the connected path of source node and destination node.
In the above method the disjoint sets are all the sets with single vertex, and we have used
union operation to merge two sets where one contains the parent node and other contains
the child node.
Below are implementations of above approach .
C++
720
Chapter 91. Calculate number of nodes between two vertices in an acyclic Graph by
Disjoint Union method
721
Chapter 91. Calculate number of nodes between two vertices in an acyclic Graph by
Disjoint Union method
i = p[i];
}
return count ;
}
// Driver program to test above function
int main()
{
// adjacency list for graph
vector < int > adjac[7];
// creating graph, keeping length of
// adjacency list as (1 + no of nodes)
// as index ranges from (0 to n-1)
adjac[1].push_back(4);
adjac[4].push_back(1);
adjac[5].push_back(4);
adjac[4].push_back(5);
adjac[4].push_back(2);
adjac[2].push_back(4);
adjac[2].push_back(6);
adjac[6].push_back(2);
adjac[6].push_back(3);
adjac[3].push_back(6);
cout << totalNodes(adjac, 7, 1, 3);
return 0;
}
Java
722
Chapter 91. Calculate number of nodes between two vertices in an acyclic Graph by
Disjoint Union method
723
Chapter 91. Calculate number of nodes between two vertices in an acyclic Graph by
Disjoint Union method
Output:
724
Chapter 91. Calculate number of nodes between two vertices in an acyclic Graph by
Disjoint Union method
Source
https://www.geeksforgeeks.org/number-nodes-two-vertices-acyclic-graph-disjoint-union-method/
725
Chapter 92
Star graph : Star graph is a special type of graph in which n-1 vertices have degree 1 and
a single vertex have degree n – 1. This looks like that n – 1 vertices are connected to a
single central vertex. A star graph with total n – vertex is termed as Sn.
Here is an illustration for the star graph :
726
Chapter 92. Check for star graph
Approach : Just traverse whole matrix and record the number of vertices having degree 1
and degree n-1. If number of vertices having degree 1 is n-1 and number of vertex having
degree n-1 is 1 then our graph should be a star graph other-wise it should be not.
Note:
C++
727
Chapter 92. Check for star graph
Java
728
Chapter 92. Check for star graph
729
Chapter 92. Check for star graph
Python3
730
Chapter 92. Check for star graph
mat[1][1] == 0)
# check for Sn (n>2)
for i in range(0, size) :
degreeI = 0
for j in range(0, size) :
if (mat[i][j]) :
degreeI = degreeI + 1
if (degreeI == 1) :
vertexD1 = vertexD1 + 1
elif (degreeI == size - 1):
vertexDn_1 = vertexDn_1 + 1
return (vertexD1 == (size - 1) and
vertexDn_1 == 1)
# Driver code
mat = [[0, 1, 1, 1],
[1, 0, 0, 0],
[1, 0, 0, 0],
[1, 0, 0, 0]]
if(checkStar(mat)) :
print ("Star Graph")
else :
print ("Not a Star Graph")
# This code is contributed by
# Manish Shaw(manishshaw1)
C#
731
Chapter 92. Check for star graph
{
// initialize number of
// vertex with deg 1 and n-1
int vertexD1 = 0, vertexDn_1 = 0;
// check for S1
if (size == 1)
return (mat[0, 0] == 0);
// check for S2
if (size == 2)
return (mat[0, 0] == 0 &&
mat[0, 1] == 1 &&
mat[1, 0] == 1 &&
mat[1, 1] == 0);
// check for Sn (n>2)
for (int i = 0; i < size; i++)
{
int degreeI = 0;
for (int j = 0; j < size; j++)
if (mat[i, j] == 1)
degreeI++;
if (degreeI == 1)
vertexD1++;
else if (degreeI == size - 1)
vertexDn_1++;
}
return (vertexD1 == (size - 1) &&
vertexDn_1 == 1);
}
// Driver code
static void Main()
{
int [,]mat = new int[4, 4]{{0, 1, 1, 1},
{1, 0, 0, 0},
{1, 0, 0, 0},
{1, 0, 0, 0}};
if (checkStar(mat))
Console.Write("Star Graph");
else
Console.Write("Not a Star Graph");
}
}
732
Chapter 92. Check for star graph
PHP
<?php
// PHP to find whether
// given graph is star
// or not
// define the size
// of incidence matrix
$size = 4;
// function to
// find star graph
function checkStar($mat)
{
global $size;
// initialize number of
// vertex with deg 1 and n-1
$vertexD1 = 0;
$vertexDn_1 = 0;
// check for S1
if ($size == 1)
return ($mat[0][0] == 0);
// check for S2
if ($size == 2)
return ($mat[0][0] == 0 &&
$mat[0][1] == 1 &&
$mat[1][0] == 1 &&
$mat[1][1] == 0 );
// check for Sn (n>2)
for ($i = 0; $i < $size; $i++)
{
$degreeI = 0;
for ($j = 0; $j < $size; $j++)
if ($mat[$i][$j])
$degreeI++;
if ($degreeI == 1)
$vertexD1++;
else if ($degreeI == $size - 1)
$vertexDn_1++;
733
Chapter 92. Check for star graph
}
return ($vertexD1 == ($size - 1) &&
$vertexDn_1 == 1);
}
// Driver code
$mat = array(array(0, 1, 1, 1),
array(1, 0, 0, 0),
array(1, 0, 0, 0),
array(1, 0, 0, 0));
if(checkStar($mat))
echo ("Star Graph");
else
echo ("Not a Star Graph");
// This code is contributed by
// Manish Shaw(manishshaw1)
?>
Output:
Star Graph
Improved By : manishshaw1
Source
https://www.geeksforgeeks.org/check-star-graph/
734
Chapter 93
Check if a given directed graph is strongly connected Set 2 (Kosaraju using BFS) - Geeks-
forGeeks
Given a directed graph, find out whether the graph is strongly connected or not. A directed
graph is strongly connected if there is a path between any two pairs of vertices. There
are different methods to check the connectivity of directed graph but one of the optimized
method is Kosaraju’s DFS based simple algorithm.
Kosaraju’s BFS based simple algorithm also work on the same principle as DFS based
algorithm does.
735
Chapter 93. Check if a given directed graph is strongly connected Set 2 (Kosaraju using
BFS)
The idea is again simple if every node can be reached from a vertex v, and every node can
reach same vertex v, then the graph is strongly connected. In step 2, we check if all vertices
are reachable from v. In step 5, we check if all vertices can reach v (In reversed graph, if all
vertices are reachable from v, then all vertices can reach v in original graph).
Explanation with some examples:
Example 1 :
Given a directed to check if it is strongly connected or not.
736
Chapter 93. Check if a given directed graph is strongly connected Set 2 (Kosaraju using
BFS)
737
Chapter 93. Check if a given directed graph is strongly connected Set 2 (Kosaraju using
BFS)
738
Chapter 93. Check if a given directed graph is strongly connected Set 2 (Kosaraju using
BFS)
queue.push_back(*i);
}
}
}
}
// Function that returns reverse (or transpose) of this graph
Graph Graph::getTranspose()
{
Graph g(V);
for (int v = 0; v < V; v++)
{
// Recur for all the vertices adjacent to this vertex
list<int>::iterator i;
for (i = adj[v].begin(); i != adj[v].end(); ++i)
g.adj[*i].push_back(v);
}
return g;
}
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w); // Add w to v’s list.
}
// The main function that returns true if graph
// is strongly connected
bool Graph::isSC()
{
// St1p 1: Mark all the vertices as not
// visited (For first BFS)
bool visited[V];
for (int i = 0; i < V; i++)
visited[i] = false;
// Step 2: Do BFS traversal starting
// from first vertex.
BFSUtil(0, visited);
// If BFS traversal doesn’t visit all
// vertices, then return false.
for (int i = 0; i < V; i++)
if (visited[i] == false)
return false;
// Step 3: Create a reversed graph
Graph gr = getTranspose();
739
Chapter 93. Check if a given directed graph is strongly connected Set 2 (Kosaraju using
BFS)
Output:
Yes
No
740
Chapter 93. Check if a given directed graph is strongly connected Set 2 (Kosaraju using
BFS)
Source
https://www.geeksforgeeks.org/check-given-directed-graph-strongly-connected-set-2-kosaraju-using-bfs/
741
Chapter 94
It is not possible to color a cycle graph with an odd cycle using two colors.
742
Chapter 94. Check if a given graph is Bipartite using DFS
In the previous post, an approach using BFS has been discussed. In this post, an approach
using DFS has been implemented. Given below is the algorithm to check for bipartiteness
of a graph.
• Use a color[] array which stores 0 or 1 for every node which denotes opposite colors.
• Call the function DFS from any node.
• If the node u has not been visited previously, then assign !color[v] to color[u] and call
DFS again to visit nodes connected to u.
• If at any point, color[u] is equal to color[v], then the node is bipartite.
• Modify the DFS function such that it returns a boolean value at the end.
743
Chapter 94. Check if a given graph is Bipartite using DFS
adj[v].push_back(u);
}
// function to check whether a graph is bipartite or not
bool isBipartite(vector<int> adj[], int v,
vector<bool>& visited, vector<int>& color)
{
for (int u : adj[v]) {
// if vertex u is not explored before
if (visited[u] == false) {
// mark present vertic as visited
visited[u] = true;
// mark its color opposite to its parent
color[u] = !color[v];
// if the subtree rooted at vertex v is not bipartite
if (!isBipartite(adj, u, visited, color))
return false;
}
// if two adjacent are colored with same color then
// the graph is not bipartite
else if (color[u] == color[v])
return false;
}
return true;
}
// Driver Code
int main()
{
// no of nodes
int N = 6;
// to maintain the adjacency list of graph
vector<int> adj[N + 1];
// to keep a check on whether
// a node is discovered or not
vector<bool> visited(N + 1);
// to color the vertices
// of graph with 2 color
vector<int> color(N + 1);
744
Chapter 94. Check if a given graph is Bipartite using DFS
// adding edges to the graph
addEdge(adj, 1, 2);
addEdge(adj, 2, 3);
addEdge(adj, 3, 4);
addEdge(adj, 4, 5);
addEdge(adj, 5, 6);
addEdge(adj, 6, 1);
// marking the source node as visited
visited[1] = true;
// marking the source node with a color
color[1] = 0;
// Function to check if the graph
// is Bipartite or not
if (isBipartite(adj, 1, visited, color)) {
cout << "Graph is Bipartite";
}
else {
cout << "Graph is not Bipartite";
}
return 0;
}
Output:
Graph is Bipartite
Source
https://www.geeksforgeeks.org/check-if-a-given-graph-is-bipartite-using-dfs/
745
Chapter 95
746
Chapter 95. Check if a given graph is tree or not
For an undirected graph we can either use BFSor DFSto detect above two properties.
How to detect cycle in an undirected graph?
We can either use BFS or DFS. For every visited vertex ‘v’, if there is an adjacent ‘u’ such
that u is already visited and u is not parent of v, then there is a cycle in graph. If we don’t
find such an adjacent for any vertex, we say that there is no cycle (SeeDetect cycle in an
undirected graph for more details).
How to check for connectivity?
Since the graph is undirected, we can start BFS or DFS from any vertex and check if all
vertices are reachable or not. If all vertices are reachable, then graph is connected, otherwise
not.
C++
747
Chapter 95. Check if a given graph is tree or not
748
Chapter 95. Check if a given graph is tree or not
Java
749
Chapter 95. Check if a given graph is tree or not
adj[v].add(w);
adj[w].add(v);
}
// A recursive function that uses visited[] and parent
// to detect cycle in subgraph reachable from vertex v.
Boolean isCyclicUtil(int v, Boolean visited[], int parent)
{
// Mark the current node as visited
visited[v] = true;
Integer i;
// Recur for all the vertices adjacent to this vertex
Iterator<Integer> it = adj[v].iterator();
while (it.hasNext())
{
i = it.next();
// If an adjacent is not visited, then recur for
// that adjacent
if (!visited[i])
{
if (isCyclicUtil(i, visited, v))
return true;
}
// If an adjacent is visited and not parent of
// current vertex, then there is a cycle.
else if (i != parent)
return true;
}
return false;
}
// Returns true if the graph is a tree, else false.
Boolean isTree()
{
// Mark all the vertices as not visited and not part
// of recursion stack
Boolean visited[] = new Boolean[V];
for (int i = 0; i < V; i++)
visited[i] = false;
// The call to isCyclicUtil serves multiple purposes
// It returns true if graph reachable from vertex 0
// is cyclcic. It also marks all vertices reachable
// from 0.
if (isCyclicUtil(0, visited, -1))
750
Chapter 95. Check if a given graph is tree or not
return false;
// If we find a vertex which is not reachable from 0
// (not marked by isCyclicUtil(), then we return false
for (int u = 0; u < V; u++)
if (!visited[u])
return false;
return true;
}
// Driver method
public static void main(String args[])
{
// Create a graph given in the above diagram
Graph g1 = new Graph(5);
g1.addEdge(1, 0);
g1.addEdge(0, 2);
g1.addEdge(0, 3);
g1.addEdge(3, 4);
if (g1.isTree())
System.out.println("Graph is Tree");
else
System.out.println("Graph is not Tree");
Graph g2 = new Graph(5);
g2.addEdge(1, 0);
g2.addEdge(0, 2);
g2.addEdge(2, 1);
g2.addEdge(0, 3);
g2.addEdge(3, 4);
if (g2.isTree())
System.out.println("Graph is Tree");
else
System.out.println("Graph is not Tree");
}
}
// This code is contributed by Aakash Hasija
Python
751
Chapter 95. Check if a given graph is tree or not
class Graph():
def __init__(self, V):
self.V = V
self.graph = defaultdict(list)
def addEdge(self, v, w):
# Add w to v ist.
self.graph[v].append(w)
# Add v to w list.
self.graph[w].append(v)
# A recursive function that uses visited[]
# and parent to detect cycle in subgraph
# reachable from vertex v.
def isCyclicUtil(self, v, visited, parent):
# Mark current node as visited
visited[v] = True
# Recur for all the vertices adjacent
# for this vertex
for i in self.graph[v]:
# If an adjacent is not visited,
# then recur for that adjacent
if visited[i] == False:
if self.isCyclicUtil(i, visited, v) == True:
return True
# If an adjacent is visited and not
# parent of current vertex, then there
# is a cycle.
elif i != parent:
return True
return False
# Returns true if the graph is a tree,
# else false.
def isTree(self):
# Mark all the vertices as not visited
# and not part of recursion stack
visited = [False] * self.V
# The call to isCyclicUtil serves multiple
# purposes. It returns true if graph reachable
# from vertex 0 is cyclcic. It also marks
# all vertices reachable from 0.
752
Chapter 95. Check if a given graph is tree or not
Output:
Graph is Tree
Graph is not Tree
Thanks to Vinit Verma for suggesting this problem and initial solution. Please write
comments if you find anything incorrect, or you want to share more information about the
topic discussed above
Source
https://www.geeksforgeeks.org/check-given-graph-tree/
753
Chapter 96
It is easy for undirected graph, we can just do a BFS and DFS starting from any
vertex. If BFS or DFS visits all vertices, then the given undirected graph is connected. This
approach won’t work for a directed graph. For example, consider the following graph which
is not strongly connected. If we start DFS (or BFS) from vertex 0, we can reach all vertices,
but if we start from any other vertex, we cannot reach all vertices.
754
Chapter 96. Check if a graph is strongly connected Set 1 (Kosaraju using DFS)
755
Chapter 96. Check if a graph is strongly connected Set 1 (Kosaraju using DFS)
756
Chapter 96. Check if a graph is strongly connected Set 1 (Kosaraju using DFS)
bool Graph::isSC()
{
// St1p 1: Mark all the vertices as not visited (For first DFS)
bool visited[V];
for (int i = 0; i < V; i++)
visited[i] = false;
// Step 2: Do DFS traversal starting from first vertex.
DFSUtil(0, visited);
// If DFS traversal doesn’t visit all vertices, then return false.
for (int i = 0; i < V; i++)
if (visited[i] == false)
return false;
// Step 3: Create a reversed graph
Graph gr = getTranspose();
// Step 4: Mark all the vertices as not visited (For second DFS)
for(int i = 0; i < V; i++)
visited[i] = false;
// Step 5: Do DFS for reversed graph starting from first vertex.
// Staring Vertex must be same starting point of first DFS
gr.DFSUtil(0, visited);
// If all vertices are not visited in second DFS, then
// return false
for (int i = 0; i < V; i++)
if (visited[i] == false)
return false;
return true;
}
// Driver program to test above functions
int main()
{
// Create graphs given in the above diagrams
Graph g1(5);
g1.addEdge(0, 1);
g1.addEdge(1, 2);
g1.addEdge(2, 3);
g1.addEdge(3, 0);
g1.addEdge(2, 4);
g1.addEdge(4, 2);
g1.isSC()? cout << "Yes\n" : cout << "No\n";
757
Chapter 96. Check if a graph is strongly connected Set 1 (Kosaraju using DFS)
Graph g2(4);
g2.addEdge(0, 1);
g2.addEdge(1, 2);
g2.addEdge(2, 3);
g2.isSC()? cout << "Yes\n" : cout << "No\n";
return 0;
}
Java
758
Chapter 96. Check if a graph is strongly connected Set 1 (Kosaraju using DFS)
n = i.next();
if (!visited[n])
DFSUtil(n,visited);
}
}
// Function that returns transpose of this graph
Graph getTranspose()
{
Graph g = new Graph(V);
for (int v = 0; v < V; v++)
{
// Recur for all the vertices adjacent to this vertex
Iterator<Integer> i = adj[v].listIterator();
while (i.hasNext())
g.adj[i.next()].add(v);
}
return g;
}
// The main function that returns true if graph is strongly
// connected
Boolean isSC()
{
// Step 1: Mark all the vertices as not visited
// (For first DFS)
Boolean visited[] = new Boolean[V];
for (int i = 0; i < V; i++)
visited[i] = false;
// Step 2: Do DFS traversal starting from first vertex.
DFSUtil(0, visited);
// If DFS traversal doesn't visit all vertices, then
// return false.
for (int i = 0; i < V; i++)
if (visited[i] == false)
return false;
// Step 3: Create a reversed graph
Graph gr = getTranspose();
// Step 4: Mark all the vertices as not visited (For
// second DFS)
for (int i = 0; i < V; i++)
visited[i] = false;
// Step 5: Do DFS for reversed graph starting from
759
Chapter 96. Check if a graph is strongly connected Set 1 (Kosaraju using DFS)
Python
760
Chapter 96. Check if a graph is strongly connected Set 1 (Kosaraju using DFS)
class Graph:
def __init__(self,vertices):
self.V= vertices #No. of vertices
self.graph = defaultdict(list) # default dictionary to store graph
# function to add an edge to graph
def addEdge(self,u,v):
self.graph[u].append(v)
#A function used by isSC() to perform DFS
def DFSUtil(self,v,visited):
# Mark the current node as visited
visited[v]= True
#Recur for all the vertices adjacent to this vertex
for i in self.graph[v]:
if visited[i]==False:
self.DFSUtil(i,visited)
# Function that returns reverse (or transpose) of this graph
def getTranspose(self):
g = Graph(self.V)
# Recur for all the vertices adjacent to this vertex
for i in self.graph:
for j in self.graph[i]:
g.addEdge(j,i)
return g
# The main function that returns true if graph is strongly connected
def isSC(self):
# Step 1: Mark all the vertices as not visited (For first DFS)
visited =[False]*(self.V)
# Step 2: Do DFS traversal starting from first vertex.
self.DFSUtil(0,visited)
# If DFS traversal doesnt visit all vertices, then return false
if any(i == False for i in visited):
return False
761
Chapter 96. Check if a graph is strongly connected Set 1 (Kosaraju using DFS)
# Step 3: Create a reversed graph
gr = self.getTranspose()
# Step 4: Mark all the vertices as not visited (For second DFS)
visited =[False]*(self.V)
# Step 5: Do DFS for reversed graph starting from first vertex.
# Staring Vertex must be same starting point of first DFS
gr.DFSUtil(0,visited)
# If all vertices are not visited in second DFS, then
# return false
if any(i == False for i in visited):
return False
return True
# Create a graph given in the above diagram
g1 = Graph(5)
g1.addEdge(0, 1)
g1.addEdge(1, 2)
g1.addEdge(2, 3)
g1.addEdge(3, 0)
g1.addEdge(2, 4)
g1.addEdge(4, 2)
print "Yes" if g1.isSC() else "No"
g2 = Graph(4)
g2.addEdge(0, 1)
g2.addEdge(1, 2)
g2.addEdge(2, 3)
print "Yes" if g2.isSC() else "No"
#This code is contributed by Neelam Yadav
Output:
Yes
No
762
Chapter 96. Check if a graph is strongly connected Set 1 (Kosaraju using DFS)
connected or not in one traversal using Tarjan’s Algorithm to find Strongly Connected
Components.
Exercise:
Can we use BFS instead of DFS in above algorithm? See this.
References:
http://www.ieor.berkeley.edu/~hochbaum/files/ieor266-2012.pdf
Source
https://www.geeksforgeeks.org/connectivity-in-a-directed-graph/
763
Chapter 97
764
Chapter 97. Check if a graphs has a cycle of odd length
The idea is based on an important fact that a graph does not contain a cycle of odd length
if and only if it is Bipartite, i.e., it can be colored with two colors.
It is obvious that if a graph has odd length cycle then it cannot be Bipartite. In Bipartite
graph there are two sets of vertices such that no vertex in a set is connected with any
other vertex of same set). For a cycle of odd length, two vertices must of same set must be
connected which contradicts Bipartite definition.
Let us understand converse, if a graph has no odd cycle then it must be Bipartite. Below is a
induction based proof of this taken from http://infohost.nmt.edu/~math/faculty/barefoot/
Math321Spring98/BipartiteGraphsAndEvenCycles.html
Assume that (X, Y) is a bipartition of G and let C = u1 , u2 , . . . , uk be a cycle of G, where
u1 is in the vertex set X (abbreviated u1 � X). If u1 � X then u2 � Y, . . . and, in general,
u2j+1 � X and u2i � Y. Since C is a cycle, uk � Y, so that k = 2s for some positive integer s.
Therefore cycle C is even.
Assume that graph G has no odd cycles. It will be shown that such a graph is bipartite.
The proof is induction on the number of edges. The assertion is clearly true for a graph
with at most one edge. Assume that every graph with no odd cycles and at most q edges is
bipartite and let G be a graph with q + 1 edges and with no odd cycles. Let e = uv be an
edge of G and consider the graph H = G – uv. By induction, H has a bipartition (X, Y). If
e has one end in X and the other end in Y then (X, Y ) is a bipartition of G. Hence, assume
that u and v are in X. If there were a path, P, between u and v in H then the length of P
would be even. Thus, P + uv would be an odd cycle of G. Therefore, u and v must be in
lie in differenet “pieces” or components of H. Thus, we have:
765
Chapter 97. Check if a graphs has a cycle of odd length
Therefore we conclude that every graph with no odd cycles is bipartite. One can construct
a bipartition as follows:
(1) Choose an arbitrary vertex x0 and set X0 = {x0 }.
(2) Let Y0 be the set of all vertices adjacent to x0 and iterate steps 3-4.
(3) Let Xk be the set of vertices not chosen that are adjacent to a vertex of Yk-1 .
(4) Let Yk be the set of vertices not chosen that are adjacent to a vertex of Xk-1 .
(5) If all vertices of G have been chosen then
X = X0 � X1 � X2 �. . . and Y = Y0 � Y1 � Y2 � . . .
766
Chapter 97. Check if a graphs has a cycle of odd length
Below is code to check if a graph has odd cycle or not. The code basically checks whether
graph is Bipartite.
C++
767
Chapter 97. Check if a graphs has a cycle of odd length
Java
768
Chapter 97. Check if a graphs has a cycle of odd length
769
Chapter 97. Check if a graphs has a cycle of odd length
// color as u
else if (G[u][v] == 1 && colorArr[v] ==
colorArr[u])
return true;
}
}
// If we reach here, then all adjacent
// vertices can be colored with alternate
// color
return false;
}
/* Driver program to test above function */
public static void main(String[] args)
{
int G[][] = {{0, 1, 0, 1},
{1, 0, 1, 0},
{0, 1, 0, 1},
{1, 0, 1, 0}};
if (containsOdd(G, 0))
System.out.println("Yes") ;
else
System.out.println("No");
}
}
// This code is contributed by Arnav Kr. Mandal.
Output :
No
The above algorithm works only if the graph is strongly connected. We can extend it for
the cases when graph is not strongly connected (Please refer this for details). In above code,
we always start with source 0 and assume that vertices are visited from it. One important
observation is a graph with no edges is also Bipiartite. Note that the Bipartite condition
says all edges should be from one set to another.
Source
https://www.geeksforgeeks.org/check-graphs-cycle-odd-length/
770
Chapter 98
One solution is to find all bridges in given graph and then check if given edge is a bridge or
not.
A simpler solution is to remove the edge, check if graph remains connect after removal or
not, finally add the edge back. We can always find if an undirected is connected or not
by finding all reachable vertices from any vertex. If count of reachable vertices is equal to
number of vertices in graph, then the graph is connected else not. We can find all reachable
vertices either using BFS or DFS. Below are complete steps.
1) Remove the given edge
2) Find all reachable vertices from any vertex. We have chosen first vertex in below imple-
mentation.
3) If count of reachable nodes is V, then return false [given is not Bridge]. Else return yes.
771
Chapter 98. Check if removing a given edge disconnects a graph
772
Chapter 98. Check if removing a given edge disconnects a graph
773
Chapter 98. Check if removing a given edge disconnects a graph
Output :
Yes
Source
https://www.geeksforgeeks.org/check-removing-given-edge-disconnects-given-graph/
774
Chapter 99
Input : N = 3, M = 2
Edges are:
1) 1-2
2) 2-3
P = {1, 2, 3}
Output : YES
Explanation :
Since there are edges between
1-2 and 2-3, therefore we can
have DFS in the order 1-2-3
Input : N = 3, M = 2
Edges are:
1) 1-2
2) 2-3
P = {1, 3, 2}
Output : NO
Explanation :
Since there is no edge between 1 and 3,
the DFS traversal is not possible
775
Chapter 99. Check if the given permutation is a valid DFS of graph
1. Store the indexes of each number in the given permutation in a Hash map.
2. Sort every adjacency list according to the indexes of permutation since there is need
to maintain the order.
3. Perform the Depth First Traversal Search with source node as 1st number of given
permutation.
4. Keep a counter variable and at every recursive call, check if the counter has reached
the number of nodes, i.e. N and set the flag as 1. If the flag is 0 after complete DFS,
answer is ‘NO’ otherwise ‘YES’
776
Chapter 99. Check if the given permutation is a valid DFS of graph
777
Chapter 99. Check if the given permutation is a valid DFS of graph
// DFS traversal of the
// vertices reachable from v.
void Graph::DFS(int v, int Perm[])
{
// Increment counter for
// every node being traversed
counter++;
// Check if counter has
// reached number of vertices
if (counter == V) {
// Set flag to 1
flag = 1;
return;
}
// Recur for all vertices adjacent
// to this vertices only if it
// lies in the given permutation
list<int>::iterator i;
for (i = adj[v].begin();
i != adj[v].end(); i++)
{
// if the current node equals to
// current element of permutation
if (*i == Perm[counter])
DFS(*i, Perm);
}
}
// Returns true if P[] is a valid DFS of given
// graph. In other words P[] can be obtained by
// doing a DFS of the graph.
bool checkPermutation(int N, int M,
vector<pair<int, int> > V, int P[])
{
// Create the required graph with
// N vertices and M edges
Graph G(N);
// Add Edges to Graph G
for (int i = 0; i < M; i++)
G.addEdge(V[i].first, V[i].second);
for (int i = 0; i < N; i++)
778
Chapter 99. Check if the given permutation is a valid DFS of graph
mp[P[i]] = i;
// Sort every adjacency
// list according to HashMap
for (int i = 1; i <= N; i++)
G.adj[i].sort(cmp);
// Call DFS with source node as P[0]
G.DFS(P[0], P);
// If Flag has been set to 1, means
// given permutation is obtained
// by DFS on given graph
return flag;
}
// Driver code
int main()
{
// Number of vertices and number of edges
int N = 3, M = 2;
// Vector of pair to store edges
vector<pair<int, int> > V;
V.push_back(make_pair(1, 2));
V.push_back(make_pair(2, 3));
int P[] = { 1, 2, 3 };
// Return the answer
if (checkPermutation(N, M, V, P))
cout << "YES" << endl;
else
cout << "NO" << endl;
return 0;
}
Output:
YES
Source
https://www.geeksforgeeks.org/check-given-permutation-valid-dfs-graph/
779
Chapter 100
Check if there is a cycle with odd weight sum in an undirected graph - GeeksforGeeks
Given a weighted and undirected graph, we need to find if a cycle exist in this graph such
that the sum of weights of all the edges in that cycle comes out to be odd.
Examples:
780
Chapter 100. Check if there is a cycle with odd weight sum in an undirected graph
The solution is based on the fact that “If a graph has no odd length cycle then it must be
Bipartite, i.e., it can be colored with two colors”
The idea is to covert given problem to a simpler problem where we have to just check if
there is cycle of odd length or not. To convert, we do following
1. Convert all even weight edges into two edges of unit weight.
2. Convert all odd weight edges to a single edge of unit weight.
Let’s make an another graph for graph shown above (in example 1)
Here, edges [1 — 2] have be broken in two parts such that [1-pseudo1-2] a pseudo node has
been introduced. We are doing this so that each of our even weighted edge is taken into
consideration twice while the edge with odd weight is counted only once. Doing this would
help us further when we color our cycle. We assign all the edges with weight 1 and then by
using 2 color method traverse the whole graph. Now we start coloring our modified graph
using two colors only. In a cycle with even number of nodes, when we color it using two
colors only, none of the two adjacent edges have the same color. While if we try coloring a
cycle having odd number of edges, surely a situation arises where two adjacent edges have
the same color. This is our pick! Thus, if we are able to color the modified graph completely
781
Chapter 100. Check if there is a cycle with odd weight sum in an undirected graph
using 2 colors only in a way no two adjacent edges get the same color assigned to them then
there must be either no cycle in the graph or a cycle with even number of nodes. If any
conflict arises while coloring a cycle with 2 colors only, then we have an odd cycle in our
graph.
782
Chapter 100. Check if there is a cycle with odd weight sum in an undirected graph
}
return true;
}
// This function returns true if graph G[V][V] is two
// colorable, else false
bool twoColor(vector<int>G[], int N){
// Create a color array to store colors assigned
// to all veritces. Vertex number is used as index
// in this array. The value '-1' of colorArr[i]
// is used to indicate that no color is assigned
// to vertex 'i'. The value 1 is used to indicate
// first color is assigned and value 0 indicates
// second color is assigned.
int colorArr[N];
for (int i = 1; i <= N; ++i)
colorArr[i] = -1;
// As we are dealing with graph, the input might
// come as a forest, thus start coloring from a
// node and if true is returned we'll know that
// we successfully colored the subpart of our
// forest and we start coloring again from a new
// uncolored node. This way we cover the entire forest.
for (int i = 1; i <= N; i++)
if (colorArr[i] == -1)
if (twoColorUtil(G, i, N, colorArr) == false)
return false;
return true;
}
// Returns false if an odd cycle is present else true
// int info[][] is the information about our graph
// int n is the number of nodes
// int m is the number of informations given to us
bool isOddSum(int info[][3],int n,int m){
// Declaring adjacency list of a graph
// Here at max, we can encounter all the edges with
// even weight thus there will be 1 pseudo node
// for each edge
vector<int> G[2*n];
int pseudo = n+1;
int pseudo_count = 0;
783
Chapter 100. Check if there is a cycle with odd weight sum in an undirected graph
784
Chapter 100. Check if there is a cycle with odd weight sum in an undirected graph
{4, 3, 1},
{4, 1, 20}};
// This function break the even weighted edges in
// two parts. Makes the adjacency representation
// of the graph and sends it for two coloring.
if (isOddSum(info, n, m) == true)
cout << "No\n";
else
cout << "Yes\n";
return 0;
}
Output:
No
Source
https://www.geeksforgeeks.org/check-if-there-is-a-cycle-with-odd-weight-sum-in-an-undirected-graph/
785
Chapter 101
Note that 1 and 5 lie on same root to leaf path, so do 1 and 6, but 2 and 6 are not on same
root to leaf path.
It is obvious that Depth First Search technique is to be used to solve above problem, the
main problem is how to respond to multiple queries fast. Here our graph is a tree which
may have any number of children. Now DFS in a tree if started from root node proceeds
in a depth search manner i.e. Suppose root has three children and those children have only
one child with them so if DFS is started then it first visits the first child of root node then
will go deep to the child of that node. The situation with a small tree can be shown as
follows:
The order of visiting the nodes will be – 1 2 5 3 6 4 7 .
Thus other children nodes are visited later until completely one child is succesfully visited
till depth. To simplify this if we assume that we have a watch in our hand and we start
786
Chapter 101. Check if two nodes are on same path in a tree
• If given pair of nodes follows any of the two conditions, then they are on the same
root to leaf path.
• Else not on same path (If two nodes are on different paths it means that no one is in
subtree of each other).
Pseudo Code
We use a global variable time which will be incremented as dfs for a node begins and will
also be incremented after
DFS(v)
increment timer
Intime[v] = timer
mark v as visited
for all u that are children of v
DFS(u)
increment timer
Outtime[v] = timer
end
787
Chapter 101. Check if two nodes are on same path in a tree
788
Chapter 101. Check if two nodes are on same path in a tree
// Driver code
int main()
{
// Let us create above shown tree
int n = 9; // total number of nodes
vector<int> graph[n+1];
graph[1].push_back(2);
graph[1].push_back(3);
graph[3].push_back(6);
graph[2].push_back(4);
graph[2].push_back(5);
graph[5].push_back(7);
graph[5].push_back(8);
graph[5].push_back(9);
// Start dfs (here root node is 1)
dfs(graph, 1);
// below are calls for few pairs of nodes
query(1, 5)? cout << "Yes\n" : cout << "No\n";
query(2, 9)? cout << "Yes\n" : cout << "No\n";
query(2, 6)? cout << "Yes\n" : cout << "No\n";
return 0;
}
Output:
Yes
Yes
No
Illustration:
From the diagram below to understand more we can have some examples. DFS algorithm
as modified above will result in the following intime and outtime for the vertex of the tree
as labelled there. Now we will consider all the cases.
789
Chapter 101. Check if two nodes are on same path in a tree
Case 1 : Nodes 2 and 4 : Node 2 has intime less than node 4 but since 4 is in its sub tree so
it will have a greater exit time than 4 . Thus conditon is valid and both are on same path.
Case 2 : Nodes 7 and 6 : Node 7 has intime less than node 6 but since both nodes are not
in each other’s sub tree so their exit time does not follow the required condition.
Source
https://www.geeksforgeeks.org/check-if-two-nodes-are-on-same-path-in-a-tree/
790
Chapter 102
Note that self loops are not considered a cycle. For example {0} is not cyclic.
The idea is to form a directed graph of array elements using given set of rules. While forming
the graph we don’t make self loops as value arr[i]%n equals to 0 means no moves. Finally
791
Chapter 102. Check loop in array according to given constraints
our task reduces to detecting cycle in a directed graph. For detecting cycle, we use DFS
and in DFS if reach a node which is visited and recursion call stack, we say there is a cycle.
792
Chapter 102. Check loop in array according to given constraints
if (visited[i]==false)
if (isCycleRec(i, adj, visited, recur))
return true;
return true;
}
// Driver code
int main(void)
{
int arr[] = {2, -1, 1, 2, 2};
int n = sizeof(arr)/sizeof(arr[0]);
if (isCycle(arr, n))
cout << "Yes"<<endl;
else
cout << "No"<<endl;
return 0;
}
Output :
Yes
Source
https://www.geeksforgeeks.org/check-loop-array-according-given-constraints/
793
Chapter 103
Input : 5
2 3 1 1 1
Output : Tree
Explanation : The input array indicates that
vertex one has degree 2, vertex
two has degree 3, vertices 3, 4
and 5 have degree 1.
1
/ \
2 3
/ \
4 5
Input : 3
2 2 2
Output : Graph
1
/ \
2 - 3
794
Chapter 103. Check whether given degrees of vertices represent a Graph or Tree
The degree of a vertex is given by the number of edges incident or leaving from it.
This can simply be done using the properties of trees like –
1. Tree is connected and has no cycles while graphs can have cycles.
2. Tree has exactly n-1 edges while there is no such constraint for graph.
3. It is given that the input graph is connected. We need at least n-1 edges to connect n
nodes.
If we take the sum of all the degrees, each edge will be counted twice. Hence, for a tree
with n vertices and n – 1 edges, sum of all degrees should be 2 * (n – 1). Please refer
Handshaking Lemma for details.
So basically we need to check if sum of all degrees is 2*(n-1) ore not.
C++
795
Chapter 103. Check whether given degrees of vertices represent a Graph or Tree
Python
Output:
Tree
Source
https://www.geeksforgeeks.org/check-whether-given-degrees-vertices-represent-graph-tree/
796
Chapter 104
It doesn’t matter whether graph is weighted or unweighted, the Chinese Postman Route is
always same as Eulerian Circuit if it exists. In weighted graph the minimum possible weight
797
Chapter 104. Chinese Postman or Route Inspection Set 1 (introduction)
of Postman tour is sum of all edge weights which we get through Eulerian Circuit. We can’t
get a shorter route as we must visit all edges at-least once.
2) In weighted graph, minimum total weight of edges to duplicate so that given graph con-
798
Chapter 104. Chinese Postman or Route Inspection Set 1 (introduction)
Illustration :
3
(a)-----------------(b)
1 / | | \1
/ | | \
(c) | 5 6| (d)
\ | | /
2 \ | 4 | /1
(e)------------------(f)
As we see above graph does not contain Eulerian circuit
because is has odd degree vertices [a, b, e, f]
they all are odd degree vertices .
799
Chapter 104. Chinese Postman or Route Inspection Set 1 (introduction)
References:
https://en.wikipedia.org/wiki/Route_inspection_problem
http://www.suffolkmaths.co.uk/pages/Maths%20Projects/Projects/Topology%20and%
20Graph%20Theory/Chinese%20Postman%20Problem.pdf
Source
https://www.geeksforgeeks.org/chinese-postman-route-inspection-set-1-introduction/
800
Chapter 105
Input :
0 - - - > 1 - - - -> 4
| / \ ^
| / \ |
| / \ |
| / \ |
| / \ |
| / \ |
v v v |
2 - - - - - - - - -> 3
To clone a DAG without storing the graph itself within a hash (or dictionary in Python). To
clone, it we basically do a depth-first traversal of the nodes, taking original node’s value and
801
Chapter 105. Clone a Directed Acyclic Graph
initializing new neighboring nodes with the same value, recursively doing, till the original
graph is fully traversed. Below is the recursive approach to cloning a DAG (in Python).
We make use of dynamic lists in Python, append operation to this list happens in constant
time, hence, fast and efficient initialization of the graph.
802
Chapter 105. Clone a Directed Acyclic Graph
Output:
803
Chapter 105. Clone a Directed Acyclic Graph
edge 0x7fa03dd43908-0x7fa03dd43950:1-2
edge 0x7fa03dd43950-0x7fa03dd43998:2-3
edge 0x7fa03dd43998-0x7fa03dd439e0:3-4
edge 0x7fa03dd43908-0x7fa03dd43998:1-3
edge 0x7fa03dd43908-0x7fa03dd439e0:1-4
edge 0x7fa03dd43878-0x7fa03dd43950:0-2
Creating the DAG by appending adjacent edges to the vertex happens in O(1) time. Cloning
of the graph takes O(E+V) time.
Source
https://www.geeksforgeeks.org/clone-directed-acyclic-graph/
804
Chapter 106
805
Chapter 106. Clone an Undirected Graph
int val;
//A neighbour vector which contains addresses to
//all the neighbours of a GraphNode
vector<GraphNode*> neighbours;
};
// A function which clones a Graph and
// returns the address to the cloned
// src node
GraphNode *cloneGraph(GraphNode *src)
{
//A Map to keep track of all the
//nodes which have already been created
map<GraphNode*, GraphNode*> m;
queue<GraphNode*> q;
// Enqueue src node
q.push(src);
GraphNode *node;
// Make a clone Node
node = new GraphNode();
node->val = src->val;
// Put the clone node into the Map
m[src] = node;
while (!q.empty())
{
//Get the front node from the queue
//and then visit all its neighbours
GraphNode *u = q.front();
q.pop();
vector<GraphNode *> v = u->neighbours;
int n = v.size();
for (int i = 0; i < n; i++)
{
// Check if this node has already been created
if (m[v[i]] == NULL)
{
// If not then create a new Node and
// put into the HashMap
node = new GraphNode();
node->val = v[i]->val;
m[v[i]] = node;
q.push(v[i]);
}
806
Chapter 106. Clone an Undirected Graph
807
Chapter 106. Clone an Undirected Graph
Java
808
Chapter 106. Clone an Undirected Graph
// A neighbour Vector which contains references to
// all the neighbours of a GraphNode
Vector<GraphNode> neighbours;
public GraphNode(int val)
{
this.val = val;
neighbours = new Vector<GraphNode>();
}
}
class Graph
{
// A method which clones the graph and
// returns the reference of new cloned source node
public GraphNode cloneGraph(GraphNode source)
{
Queue<GraphNode> q = new LinkedList<GraphNode>();
q.add(source);
// An HashMap to keep track of all the
// nodes which have already been created
HashMap<GraphNode,GraphNode> hm =
new HashMap<GraphNode,GraphNode>();
//Put the node into the HashMap
hm.put(source,new GraphNode(source.val));
while (!q.isEmpty())
{
// Get the front node from the queue
// and then visit all its neighbours
GraphNode u = q.poll();
// Get corresponding Cloned Graph Node
GraphNode cloneNodeU = hm.get(u);
if (u.neighbours != null)
{
Vector<GraphNode> v = u.neighbours;
for (GraphNode graphNode : v)
{
// Get the corresponding cloned node
// If the node is not cloned then we will
// simply get a null
GraphNode cloneNodeG = hm.get(graphNode);
// Check if this node has already been created
if (cloneNodeG == null)
809
Chapter 106. Clone an Undirected Graph
{
q.add(graphNode);
// If not then create a new Node and
// put into the HashMap
cloneNodeG = new GraphNode(graphNode.val);
hm.put(graphNode,cloneNodeG);
}
// add the 'cloneNodeG' to neighbour
// vector of the cloneNodeG
cloneNodeU.neighbours.add(cloneNodeG);
}
}
}
// Return the reference of cloned source Node
return hm.get(source);
}
// Build the desired graph
public GraphNode buildGraph()
{
/*
Note : All the edges are Undirected
Given Graph:
1--2
| |
4--3
*/
GraphNode node1 = new GraphNode(1);
GraphNode node2 = new GraphNode(2);
GraphNode node3 = new GraphNode(3);
GraphNode node4 = new GraphNode(4);
Vector<GraphNode> v = new Vector<GraphNode>();
v.add(node2);
v.add(node4);
node1.neighbours = v;
v = new Vector<GraphNode>();
v.add(node1);
v.add(node3);
node2.neighbours = v;
v = new Vector<GraphNode>();
v.add(node2);
v.add(node4);
node3.neighbours = v;
v = new Vector<GraphNode>();
v.add(node3);
810
Chapter 106. Clone an Undirected Graph
v.add(node1);
node4.neighbours = v;
return node1;
}
// BFS traversal of a graph to
// check if the cloned graph is correct
public void bfs(GraphNode source)
{
Queue<GraphNode> q = new LinkedList<GraphNode>();
q.add(source);
HashMap<GraphNode,Boolean> visit =
new HashMap<GraphNode,Boolean>();
visit.put(source,true);
while (!q.isEmpty())
{
GraphNode u = q.poll();
System.out.println("Value of Node " + u.val);
System.out.println("Address of Node " + u);
if (u.neighbours != null)
{
Vector<GraphNode> v = u.neighbours;
for (GraphNode g : v)
{
if (visit.get(g) == null)
{
q.add(g);
visit.put(g,true);
}
}
}
}
System.out.println();
}
}
// Driver code
class Main
{
public static void main(String args[])
{
Graph graph = new Graph();
GraphNode source = graph.buildGraph();
System.out.println("BFS traversal of a graph before cloning");
graph.bfs(source);
GraphNode newSource = graph.cloneGraph(source);
System.out.println("BFS traversal of a graph after cloning");
graph.bfs(newSource);
811
Chapter 106. Clone an Undirected Graph
}
}
Output in Java:
Output in C++:
812
Chapter 106. Clone an Undirected Graph
Source
https://www.geeksforgeeks.org/clone-an-undirected-graph/
813
Chapter 107
814
Chapter 107. Clustering Coefficient in Graph Theory
The local clustering coefficient for a vertex is then given by the proportion of links
between the vertices within its neighborhood divided by the number of links that could
possibly exist between them. For a directed graph, is distinct from , and therefore
for each neighborhood there are links that could exist among the
vertices within the neighborhood ( is the number of neighbors of a vertex). Thus, the
local clustering coefficient for directed graphs is given as [2]
.
An undirected graph has the property that and are considered identical. There-
fore, if a vertex has neighbors, edges could exist among the vertices
within the neighborhood. Thus, the local clustering coefficient for undirected graphs can be
defined as
That is, is the number of sub-graphs of G with 3 edges and 3 vertices, one of
.
It is simple to show that the two preceding definitions are the same, since
.
These measures are 1 if every neighbor connected to is also connected to every other
vertex within the neighborhood, and 0 if no vertex that is connected to connects to any
other vertex that is connected to .
815
Chapter 107. Clustering Coefficient in Graph Theory
Example local clustering coefficient on an undirected graph. The local clustering coefficient
of the green node is computed as the proportion of connections among its neighbours.
Here is the code to implement the above clustering coefficient in a graph. It is a part of the
networkx library and can be directly accessed using it.
816
Chapter 107. Clustering Coefficient in Graph Theory
Note: The above code is valid for undirected networks and not for the directed networks.
The code below has been run on IDLE(Python IDE of windows). You would need to
download the networkx library before you run this code. The part inside the curly braces
represent the output. It is almost similar as Ipython(for Ububtu users).
The above two values give us the global clustering coefficient of a network as well as local
clustering coefficient of a network.
Next into this series, we will talk about another centrality measure for any given network.
References
You can read more about the same at
https://en.wikipedia.org/wiki/Clustering_coefficient
http://networkx.readthedocs.io/en/networkx-1.10/index.html
.
Source
https://www.geeksforgeeks.org/clustering-coefficient-graph-theory/
817
Chapter 108
Time Complexities :
Other Points:
• We can use Dijskstra’s shortest path algorithm for finding all pair shortest paths by
running it for every vertex. But time complexity of this would be O(VE Log V) which
can go (V3 Log V) in worst case.
• Another important differentiating factor between the algorithms is their working to-
wards distributed systems. Unlike Dijkstra’s algorithm, Floyd Warshall can be imple-
mented in a distributed system, making it suitable for data structures such as Graph
of Graphs (Used in Maps).
• Lastly Floyd Warshall works for negative edge but no negative cycle, whereas Dijk-
stra’s algorithm don’t work for negative edges.
818
Chapter 108. Comparison of Dijkstra’s and Floyd-Warshall algorithms
Source
https://www.geeksforgeeks.org/comparison-dijkstras-floyd-warshall-algorithms/
819
Chapter 109
820
Chapter 109. Computer Networks Cuts and Network Flow
X from node Y.
821
Chapter 109. Computer Networks Cuts and Network Flow
• Minimal Cut : It is one which replacement of any of its member reconnects the
Graph. In other words, in a minimal cut, all the arcs are essential. The set of arcs
AB, AE and FG form A-H cut, but the cut is not minimal, because restoring arc FG
does not reconnect node A to node H.
• Minimum Cut : In a weighted graph each cut has capacity. A cut with minimum
capacity is minimum cut. In the diagram shown above the Cut-3 with capacity=10,
is the minimum cut.
• Max Flow Min Cut Theorem : The maximum flow between any two arbitrary
nodes in any graph cannot exceed the capacity of the minimum cut separating those
two nodes.
• Polling : Each station on the network is polled in some predetermined order. Between
polls, stations accumulate messages in their queues but do not transmit until they are
polled. The process by which terminals on a line are successively invited to send data.
This may occur by having a master station use a polling list to invite terminals to
send data, or by each terminal sending a poll message to the next terminal in sequence
so that it might send data, or via the use of a token as in a token ring to control the
sending of data.
• Polling Sequences : The sequence in which terminals are invited to transmit data.
This may be based on a polling list in which terminal ids are stored in the sequence
that they are to be polled.
822
Chapter 109. Computer Networks Cuts and Network Flow
• Polling Techniques :
1. Roll call Polling : A master station uses one or more polling lists to determine
the next terminal in sequence to be polled. Each station has to be polled in
turn by the central computer (controller). After the station has transmitted its
backlog of messages, it notifies the central controller with a suffix to its last packet.
After receiving this suffix packet, the controller sends a poll to the next station
in the polling sequence.
2. Hub Polling : The terminal currently in polled mode polls the next terminal
in sequence. In this case, the go-ahead (suffix) packet contains the next station
address.
A monitoring channel must be provided to indicate to the appropriate station that
it should start transmitting. Essentially the go-ahead is transmitted directly from
one station to another.
3. Token Passing : A token is passed to the next device on the network (ring or
bus) which may use it to transmit data or may let it pass to the next device.
823
Chapter 109. Computer Networks Cuts and Network Flow
Source
https://www.geeksforgeeks.org/cuts-network-flow/
824
Chapter 110
Connected Components in an
undirected graph
We strongly recommend to minimize your browser and try this yourself first.
We have discussed algorithms for finding strongly connected components in directed graphs
in following posts.
Kosaraju’s algorithm for strongly connected components.
Tarjan’s Algorithm to find Strongly Connected Components
Finding connected components for an undirected graph is an easier task. We simple need to
do either BFS or DFS starting from every unvisited vertex, and we get all strongly connected
components. Below are steps based on DFS.
825
Chapter 110. Connected Components in an undirected graph
DFSUtil(v)
1) Mark 'v' as visited.
2) Print 'v'
3) Do following for every adjacent 'u' of 'v'.
If 'u' is not visited, then recursively call DFSUtil(u)
826
Chapter 110. Connected Components in an undirected graph
827
Chapter 110. Connected Components in an undirected graph
g.connectedComponents();
return 0;
}
Output
0 1
2 3 4
Time complexity of above solution is O(V + E) as it does simple DFS for given graph.
Source
https://www.geeksforgeeks.org/connected-components-in-an-undirected-graph/
828
Chapter 111
Approach :
1- Take the input of the number of vertexes and their corresponding degree.
2- Declare adjacency matrix, mat[ ][ ] to store the graph.
829
Chapter 111. Construct a graph from given degrees of all vertices
3- To create the graph, create the first loop to connect each vertex ‘i’.
4- Second nested loop to connect the vertex ‘i’ to the every valid vertex ‘j’, next to it.
5- If the degree of vertex ‘i’ and ‘j’ are more than zero then connect them.
6- Print the adjacency matrix.
Based on the above explanation, below are implementations:
830
Chapter 111. Construct a graph from given degrees of all vertices
{
int degseq[] = { 2, 2, 1, 1, 1 };
int n = sizeof(degseq) / sizeof(degseq[0]);
printMat(degseq, n);
return 0;
}
Output:
(0) 0 1 1 0 0
(1) 1 0 0 1 0
(2) 1 0 0 0 0
(3) 0 1 0 0 0
(4) 0 0 0 0 0
Source
https://www.geeksforgeeks.org/construct-graph-given-degrees-vertices/
831
Chapter 112
Input : n = 5, k = 3
Output : 11011
Explanation : the 3 sized substring is
110 combined twice and trimming the extra
0 in the end to give 11011.
Input : n = 2, k = 8
Output : 11
Explanation : the 8 sized substring is 11......
wrapped to two places to give 11.
The naive approach would be to try every palindrome of size k starting with 1 such that
a palindrome of size n is formed. This approach has an exponential complexity.
A better way to do this is to initialize the k sized binary number with the index and
connect the palindrome in the way it should be. Like last character of palindrome should
match to first, find which indexes will be present at those locations and link them. Set
every character linked with 0th index to 1 and the string is ready. This approach will have
a linear complexity.
832
Chapter 112. Construct binary palindrome by repeated appending and trimming
In this approach, first lay the index of the k sized binary to hold into an array, for example
if n = 7, k = 3 arr becomes [0, 1, 2, 0, 1, 2, 0]. Following that in the connectchars graph,
connect the indices of the k sized binary which should be same by going through the property
of palindrome which is kth and (n – k – 1)th variable should be same, such that 0 is linked
to 1(and vice versa), 1 is linked to 2(and vice versa) and so on. After that, check what is
linked with 0 in connectchars array and make all of the associated indices one (because the
first number should be non-zero) by using dfs approach. In the dfs, pass 0, the final answer
string and the graph. Begin by making the parent 1 and checking if its children are zero,
if they are make them and their children 1. This makes only the required indices of the k
sized string one, others are left zero. Finally, the answer contains the 0 to k – 1 indexes and
corresponding to arr the digits are printed.
833
Chapter 112. Construct binary palindrome by repeated appending and trimming
Output:
1100110011
Source
https://www.geeksforgeeks.org/construct-binary-palindrome-by-repeated-appending-and-trimming/
834
Chapter 113
The problem can be solved using backtracking, that is we take a path and start walking it,
if it leads us to the destination vertex then we count the path and backtrack to take another
path. If the path doesn’t leads us to the destination vertex, we discard the path.
Backtracking for above graph can be shown like this:
The red color vertex is the source vertex and the light-blue color vertex is destination, rest
are either intermediate or discarded paths.
835
Chapter 113. Count all possible paths between two vertices
836
Chapter 113. Count all possible paths between two vertices
C++
837
Chapter 113. Count all possible paths between two vertices
};
Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V];
}
void Graph::addEdge(int u, int v)
{
// Add v to u’s list.
adj[u].push_back(v);
}
// Returns count of paths from 's' to 'd'
int Graph::countPaths(int s, int d)
{
// Mark all the vertices
// as not visited
bool *visited = new bool[V];
memset(visited, false, sizeof(visited));
// Call the recursive helper
// function to print all paths
int pathCount = 0;
countPathsUtil(s, d, visited, pathCount);
return pathCount;
}
// A recursive function to print all paths
// from 'u' to 'd'. visited[] keeps track of
// vertices in current path. path[] stores
// actual vertices and path_index is
// current index in path[]
void Graph::countPathsUtil(int u, int d, bool visited[],
int &pathCount)
{
visited[u] = true;
// If current vertex is same as destination,
// then increment count
if (u == d)
pathCount++;
// If current vertex is not destination
else
838
Chapter 113. Count all possible paths between two vertices
{
// Recur for all the vertices adjacent to
// current vertex
list<int>::iterator i;
for (i = adj[u].begin(); i != adj[u].end(); ++i)
if (!visited[*i])
countPathsUtil(*i, d, visited,
pathCount);
}
visited[u] = false;
}
// Driver Code
int main()
{
// Create a graph given in the above diagram
Graph g(4);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(0, 3);
g.addEdge(2, 0);
g.addEdge(2, 1);
g.addEdge(1, 3);
int s = 2, d = 3;
cout << g.countPaths(s, d);
return 0;
}
Java
839
Chapter 113. Count all possible paths between two vertices
840
Chapter 113. Count all possible paths between two vertices
int n = i.next();
if (!visited[n])
{
pathCount = countPathsUtil(n, d,
visited,
pathCount);
}
}
}
visited[u] = false;
return pathCount;
}
// Returns count of
// paths from 's' to 'd'
int countPaths(int s, int d)
{
// Mark all the vertices
// as not visited
boolean visited[] = new boolean[V];
Arrays.fill(visited, false);
// Call the recursive method
// to count all paths
int pathCount = 0;
pathCount = countPathsUtil(s, d,
visited,
pathCount);
return pathCount;
}
// Driver Code
public static void main(String args[])
{
Graph g = new Graph(4);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(0, 3);
g.addEdge(2, 0);
g.addEdge(2, 1);
g.addEdge(1, 3);
int s = 2, d = 3;
System.out.println(g.countPaths(s, d));
}
}
841
Chapter 113. Count all possible paths between two vertices
// This code is contributed by shubhamjd.
Output:
Source
https://www.geeksforgeeks.org/count-possible-paths-two-vertices/
842
Chapter 114
We can solve this problem using breadth first search. Main thing to observe in this problem
is that if we find two marked nodes which are at largest distance from each other considering
all pairs of marked nodes then if a node is at a distance less than K from both of these two
nodes then it will be at a distance less than K from all the marked nodes because these two
nodes represents the extreme limit of all marked nodes, if a node lies in this limit then it
will be at a distance less than K from all marked nodes otherwise not.
As in above example, node-1 and node-4 are most distant marked node so nodes which are
at distance less than 3 from these two nodes will also be at distance less than 3 from node
2 also. Now first distant marked node we can get by doing a bfs from any random node,
second distant marked node we can get by doing another bfs from marked node we just
found from the first bfs and in this bfs we can also found distance of all nodes from first
distant marked node and to find distance of all nodes from second distant marked node we
will do one more bfs, so after doing these three bfs we can get distance of all nodes from
843
Chapter 114. Count nodes within K-distance from all nodes in a set
two extreme marked nodes which can be compared with K to know which nodes fall in
K-distance range from all marked nodes.
844
Chapter 114. Count nodes within K-distance from all nodes in a set
845
Chapter 114. Count nodes within K-distance from all nodes in a set
return res;
}
// Driver code to test above methods
int main()
{
int edges[][2] =
{
{1, 0}, {0, 3}, {0, 8}, {2, 3},
{3, 5}, {3, 6}, {3, 7}, {4, 5},
{5, 9}
};
int V = sizeof(edges) / sizeof(edges[0]);
int marked[] = {1, 2, 4};
int N = sizeof(marked) / sizeof(marked[0]);
int K = 3;
cout << nodesKDistanceFromMarked(edges, V, marked, N, K);
return 0;
}
Output:
Source
https://www.geeksforgeeks.org/count-nodes-within-k-distance-from-all-nodes-in-a-set/
846
Chapter 115
So we traverse all vertices, compute sum of sizes of their adjacency lists, and finally returns
sum/2. Below c++ implementation of above idea
847
Chapter 115. Count number of edges in an undirected graph
848
Chapter 115. Count number of edges in an undirected graph
g.addEdge(0, 1 );
g.addEdge(0, 7 );
g.addEdge(1, 2 );
g.addEdge(1, 7 );
g.addEdge(2, 3 );
g.addEdge(2, 8 );
g.addEdge(2, 5 );
g.addEdge(3, 4 );
g.addEdge(3, 5 );
g.addEdge(4, 5 );
g.addEdge(5, 6 );
g.addEdge(6, 7 );
g.addEdge(6, 8 );
g.addEdge(7, 8 );
cout << g.countEdges() << endl;
return 0;
}
Output:
14
Source
https://www.geeksforgeeks.org/count-number-edges-undirected-graph/
849
Chapter 116
Approach :
1. Apply DFS on every node.
2. Increment count by one if every connected node is visited from one source.
3. Again perform DFS traversal if some nodes yet not visited.
4. Count will give the number of trees in forest.
C++
850
Chapter 116. Count number of trees in a forest
{
adj[u].push_back(v);
adj[v].push_back(u);
}
// A utility function to do DFS of graph
// recursively from a given vertex u.
void DFSUtil(int u, vector<int> adj[],
vector<bool> &visited)
{
visited[u] = true;
for (int i=0; i<adj[u].size(); i++)
if (visited[adj[u][i]] == false)
DFSUtil(adj[u][i], adj, visited);
}
// Returns count of tree is the forest
// given as adjacency list.
int countTrees(vector<int> adj[], int V)
{
vector<bool> visited(V, false);
int res = 0;
for (int u=0; u<V; u++)
{
if (visited[u] == false)
{
DFSUtil(u, adj, visited);
res++;
}
}
return res;
}
// Driver code
int main()
{
int V = 5;
vector<int> adj[V];
addEdge(adj, 0, 1);
addEdge(adj, 0, 2);
addEdge(adj, 3, 4);
cout << countTrees(adj, V);
return 0;
}
Output:
851
Chapter 116. Count number of trees in a forest
Source
https://www.geeksforgeeks.org/count-number-trees-forest/
852
Chapter 117
Input :
Vertices : 6
Edges : 1 2
1 3
5 6
Output : 1
Explanation : The Graph has 3 components : {1-2-3}, {5-6}, {4}
Out of these, the only component forming singleton graph is {4}.
The idea is simple for graph given as adjacency list representation. We traverse the list and
find the indices(representing a node) with no elements in list, i.e. no connected components.
Below is the C++ representation :
853
Chapter 117. Count single node isolated sub-graphs in a disconnected graph
Output:
Source
https://www.geeksforgeeks.org/count-single-node-isolated-sub-graphs-disconnected-graph/
854
Chapter 118
Count the number of nodes at given level in a tree using BFS. - GeeksforGeeks
Given a tree represented as undirected graph. Count the number of nodes at given level l.
It may be assumed that vertex 0 is root of the tree.
Examples:
Input : 7
0 1
0 2
1 3
1 4
1 5
2 6
2
Output : 4
Input : 6
0 1
0 2
1 3
2 4
2 5
2
Output : 3
BFS is a traversing algorithm which start traversing from a selected node (source or starting
node) and traverse the graph layer wise thus exploring the neighbour nodes (nodes which
855
Chapter 118. Count the number of nodes at given level in a tree using BFS.
are directly connected to source node). Then, move towards the next-level neighbour nodes.
As the name BFS suggests, traverse the graph breadth wise as follows:
1. First move horizontally and visit all the nodes of the current layer.
2. Move to the next layer.
In this code, while visiting each node, the level of that node is set with an increment in the
level of its parent node i.e., level[child] = level[parent] + 1. This is how the level of each
node is determined. The root node lies at level zero in the tree.
Explanation :
0 Level 0
/ \
1 2 Level 1
/ |\ |
3 4 5 6 Level 2
Given a tree with 7 nodes and 6 edges in which node 0 lies at 0 level. Level of 1 can be
updated as : level[1] = level[0] +1 as 0 is the parent node of 1. Similarly, the level of other
nodes can be updated by adding 1 to the level of their parent.
level[2] = level[0] + 1, i.e level[2] = 0 + 1 = 1.
level[3] = level[1] + 1, i.e level[3] = 1 + 1 = 2.
level[4] = level[1] + 1, i.e level[4] = 1 + 1 = 2.
level[5] = level[1] + 1, i.e level[5] = 1 + 1 = 2.
level[6] = level[2] + 1, i.e level[6] = 1 + 1 = 2.
Then, count of number of nodes which are at level l(i.e, l=2) is 4 (node:- 3, 4, 5, 6)
C++
856
Chapter 118. Count the number of nodes at given level in a tree using BFS.
857
Chapter 118. Count the number of nodes at given level in a tree using BFS.
visited[s] = true;
queue.push_back(s);
level[s] = 0;
while (!queue.empty()) {
// Dequeue a vertex from
// queue and print it
s = queue.front();
queue.pop_front();
// Get all adjacent vertices
// of the dequeued vertex s.
// If a adjacent has not been
// visited, then mark it
// visited and enqueue it
for (auto i = adj[s].begin();
i != adj[s].end(); ++i) {
if (!visited[*i]) {
// Setting the level
// of each node with
// an increment in the
// level of parent node
level[*i] = level[s] + 1;
visited[*i] = true;
queue.push_back(*i);
}
}
}
int count = 0;
for (int i = 0; i < V; i++)
if (level[i] == l)
count++;
return count;
}
// Driver program to test
// methods of graph class
int main()
{
// Create a graph given
// in the above diagram
Graph g(6);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 3);
858
Chapter 118. Count the number of nodes at given level in a tree using BFS.
g.addEdge(2, 4);
g.addEdge(2, 5);
int level = 2;
cout << g.BFS(0, level);
return 0;
}
Output:
Source
https://www.geeksforgeeks.org/count-number-nodes-given-level-using-bfs/
859
Chapter 119
In this graph if we consider 0 as head node, then the node 0, 1 and 2 are reachable. We
mark all the reachable nodes as visited. All those nodes which are not mark as visited i.e,
node 3 and 4 are non reachable nodes. Hence their count is 2.
Examples:
Input : 5
0 1
0 2
1 2
860
Chapter 119. Count the number of non-reachable nodes
3 4
Output : 2
We can either use BFS or DFS for this purpose. In below implementation DFS is used. We
do DFS from given source. Since the given graph is undirected, all the vertices that belong
to the disconnected component are non-reachable nodes. We use the visit array for this
purpose, the array which is used to keep track of non-visited vertices in DFS. In DFS, if we
start from head node it will mark all the nodes connected to the head node as visited. Then
after traversing the graph we count the number of nodes that are not mark as visited from
the head node.
861
Chapter 119. Count the number of non-reachable nodes
862
Chapter 119. Count the number of non-reachable nodes
g.addEdge(3, 4);
g.addEdge(4, 5);
g.addEdge(6, 7);
cout << g.countNotReach(2);
return 0;
}
Output:
Source
https://www.geeksforgeeks.org/count-number-non-reachable-nodes/
863
Chapter 120
Cycles of length n in an
undirected and connected graph
Input : n = 4
To solve this Problem, DFS(Depth First Search) can be effectively used. Using DFS we
find every possible path of length (n-1) for a particular source (or starting point). Then we
check if this path ends with the vertex it started with, if yes then we count this as the cycle
of length n. Notice that we looked for path of length (n-1) because the nth edge will be the
closing edge of cycle.
Every possible path of length (n-1) can be searched using only V – (n – 1) vertices (where
V is the total number of vertices).
For above example, all the cycles of length 4 can be searched using only 5-(4-1) = 2 vertices.
The reason behind this is quite simple, because we search for all possible path of length
864
Chapter 120. Cycles of length n in an undirected and connected graph
(n-1) = 3 using these 2 vertices which include the remaining 3 vertices. So, these 2 vertices
cover the cycles of remaining 3 vertices as well, and using only 3 vertices we can’t form a
cycle of length 4 anyways.
One more thing to notice is that, every vertex finds 2 duplicate cycles for every cycle that
it forms. For above example 0th vertex finds two duplicate cycle namely 0 -> 3 -> 2 ->
1 -> 0 and 0 -> 1 -> 2 -> 3 -> 0. Hence the total count must be divided by 2 because
every cycle is counted twice.
C++
865
Chapter 120. Cycles of length n in an undirected and connected graph
Java
866
Chapter 120. Cycles of length n in an undirected and connected graph
867
Chapter 120. Cycles of length n in an undirected and connected graph
Python3
868
Chapter 120. Cycles of length n in an undirected and connected graph
869
Chapter 120. Cycles of length n in an undirected and connected graph
[1, 0, 1, 0, 1],
[0, 1, 0, 1, 0]]
n = 4
print("Total cycles of length ",n," are ",countCycles(graph, n))
# this code is contributed by Shivani Ghughtyal
Output:
Source
https://www.geeksforgeeks.org/cycles-of-length-n-in-an-undirected-and-connected-graph/
870
Chapter 121
to the vertex, with loops counted twice.[1] The degree of a vertex is denoted
871
Chapter 121. Degree Centrality (Centrality Measure)
Calculating degree centrality for all the nodes in a graph takes in a dense
adjacency matrix representation of the graph, and for edges takes in a sparse
matrix representation.
The definition of centrality on the node level can be extended to the whole graph, in which
case we are speaking of graph centralization. Let be the node with highest degree
The value of is maximized when the graph contains one central node to which all
other nodes are connected (a star graph), and in this case
.
Following is the code for the calculation of the degree centrality of the graph and its various
nodes.
import networkx as nx
def degree_centrality(G, nodes):
r"""Compute the degree centrality for nodes in a bipartite network.
The degree centrality for a node `v` is the fraction of nodes
connected to it.
Parameters
----------
G : graph
A bipartite network
nodes : list or container
Container with all nodes in one bipartite node set.
872
Chapter 121. Degree Centrality (Centrality Measure)
Returns
-------
centrality : dictionary
Dictionary keyed by node with bipartite degree centrality as the value.
Notes
-----
The nodes input parameter must conatin all nodes in one bipartite node set,
but the dictionary returned contains all nodes from both bipartite node
sets.
For unipartite networks, the degree centrality values are
normalized by dividing by the maximum possible degree (which is
`n-1` where `n` is the number of nodes in G).
In the bipartite case, the maximum possible degree of a node in a
bipartite node set is the number of nodes in the opposite node set
[1]_. The degree centrality for a node `v` in the bipartite
sets `U` with `n` nodes and `V` with `m` nodes is
.. math::
d_{v} = \frac{deg(v)}{m}, \mbox{for} v \in U ,
d_{v} = \frac{deg(v)}{n}, \mbox{for} v \in V ,
where `deg(v)` is the degree of node `v`.
"""
top = set(nodes)
bottom = set(G) - top
s = 1.0/len(bottom)
centrality = dict((n,d*s) for n,d in G.degree_iter(top))
s = 1.0/len(top)
centrality.update(dict((n,d*s) for n,d in G.degree_iter(bottom)))
return centrality
The above function is invoked using the networkx library and once the library is installed,
you can eventually use it and the following code has to be written in python for the imple-
mentation of the Degree centrality of a node.
import networkx as nx
G=nx.erdos_renyi_graph(100,0.5)
d=nx.degree_centrality(G)
print(d)
873
Chapter 121. Degree Centrality (Centrality Measure)
The above result is a dictionary depicting the value of degree centrality of each node. The
above is an extension of my article series on the centrality measures. Keep networking!!!
References
You can read more about the same at
https://en.wikipedia.org/wiki/Centrality#Degree_centrality
http://networkx.readthedocs.io/en/networkx-1.10/index.html
Source
https://www.geeksforgeeks.org/degree-centrality-centrality-measure/
874
Chapter 122
In above tree,
We have 6 choices for edge deletion,
edge 0-1, subtree sum difference = 21 - 2 = 19
edge 0-2, subtree sum difference = 14 - 9 = 5
edge 0-3, subtree sum difference = 15 - 8 = 7
edge 2-4, subtree sum difference = 20 - 3 = 17
edge 2-5, subtree sum difference = 18 - 5 = 13
edge 3-6, subtree sum difference = 21 - 2 = 19
We can solve this problem using DFS. One simple solution is to delete each edge one by
one and check subtree sum difference. Finally choose the minimum of them. This approach
takes quadratic amount of time. An efficient method can solve this problem in linear time
by calculating the sum of both subtrees using total sum of the tree. We can get the sum of
other tree by subtracting sum of one subtree from the total sum of tree, in this way subtree
sum difference can be calculated at each node in O(1) time. First we calculate the weight
of complete tree and then while doing the DFS at each node, we calculate its subtree sum,
by using these two values we can calculate subtree sum difference.
In below code, another array subtree is used to store sum of subtree rooted at node i in
subtree[i]. DFS is called with current node index and parent index each time to loop over
875
Chapter 122. Delete Edge to minimize subtree sum difference
876
Chapter 122. Delete Edge to minimize subtree sum difference
Output:
Source
https://www.geeksforgeeks.org/delete-edge-minimize-subtree-sum-difference/
877
Chapter 123
878
Chapter 123. Depth First Search or DFS for a Graph
879
Chapter 123. Depth First Search or DFS for a Graph
list<int>::iterator i;
for (i = adj[v].begin(); i != adj[v].end(); ++i)
if (!visited[*i])
DFSUtil(*i, visited);
}
// DFS traversal of the vertices reachable from v.
// It uses recursive DFSUtil()
void Graph::DFS(int v)
{
// Mark all the vertices as not visited
bool *visited = new bool[V];
for (int i = 0; i < V; i++)
visited[i] = false;
// Call the recursive helper function
// to print DFS traversal
DFSUtil(v, visited);
}
int main()
{
// Create a graph given in the above diagram
Graph g(4);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 2);
g.addEdge(2, 0);
g.addEdge(2, 3);
g.addEdge(3, 3);
cout << "Following is Depth First Traversal"
" (starting from vertex 2) \n";
g.DFS(2);
return 0;
}
Java
880
Chapter 123. Depth First Search or DFS for a Graph
881
Chapter 123. Depth First Search or DFS for a Graph
Python
882
Chapter 123. Depth First Search or DFS for a Graph
Output:
883
Chapter 123. Depth First Search or DFS for a Graph
884
Chapter 123. Depth First Search or DFS for a Graph
885
Chapter 123. Depth First Search or DFS for a Graph
886
Chapter 123. Depth First Search or DFS for a Graph
void Graph::DFSUtil(int v, bool visited[])
{
// Mark the current node as visited and print it
visited[v] = true;
cout << v << " ";
// Recur for all the vertices adjacent to this vertex
list<int>::iterator i;
for(i = adj[v].begin(); i != adj[v].end(); ++i)
if(!visited[*i])
DFSUtil(*i, visited);
}
// The function to do DFS traversal. It uses recursive DFSUtil()
void Graph::DFS()
{
// Mark all the vertices as not visited
bool *visited = new bool[V];
for (int i = 0; i < V; i++)
visited[i] = false;
// Call the recursive helper function to print DFS traversal
// starting from all vertices one by one
for (int i = 0; i < V; i++)
if (visited[i] == false)
DFSUtil(i, visited);
}
int main()
{
// Create a graph given in the above diagram
Graph g(4);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 2);
g.addEdge(2, 0);
g.addEdge(2, 3);
g.addEdge(3, 3);
cout << "Following is Depth First Traversaln";
g.DFS();
return 0;
}
Java
887
Chapter 123. Depth First Search or DFS for a Graph
888
Chapter 123. Depth First Search or DFS for a Graph
Python
889
Chapter 123. Depth First Search or DFS for a Graph
Output:
890
Chapter 123. Depth First Search or DFS for a Graph
0 1 2 3
Time Complexity: O(V+E) where V is number of vertices in the graph and E is number of
edges in the graph.
• Applications of DFS.
• Breadth First Traversal for a Graph
Source
https://www.geeksforgeeks.org/depth-first-search-or-dfs-for-a-graph/
891
Chapter 124
892
Chapter 124. Detect a negative cycle in a Graph (Bellman Ford)
Negative weights are found in various applications of graphs. For example, instead of
paying cost for a path, we may get some advantage if we follow the path.
Examples:
Input : 4 4
0 1 1
1 2 -1
2 3 -1
3 0 -1
Output : Yes
The graph contains a negative cycle.
893
Chapter 124. Detect a negative cycle in a Graph (Bellman Ford)
struct Graph {
// V-> Number of vertices, E-> Number of edges
int V, E;
// graph is represented as an array of edges.
struct Edge* edge;
};
// Creates a graph with V vertices and E edges
struct Graph* createGraph(int V, int E)
{
struct Graph* graph = new Graph;
graph->V = V;
graph->E = E;
graph->edge = new Edge[graph->E];
return graph;
}
// The main function that finds shortest distances
// from src to all other vertices using Bellman-
// Ford algorithm. The function also detects
// negative weight cycle
bool isNegCycleBellmanFord(struct Graph* graph,
int src)
{
int V = graph->V;
int E = graph->E;
int dist[V];
// Step 1: Initialize distances from src
// to all other vertices as INFINITE
for (int i = 0; i < V; i++)
dist[i] = INT_MAX;
dist[src] = 0;
// Step 2: Relax all edges |V| - 1 times.
// A simple shortest path from src to any
// other vertex can have at-most |V| - 1
// edges
for (int i = 1; i <= V - 1; i++) {
for (int j = 0; j < E; j++) {
int u = graph->edge[j].src;
int v = graph->edge[j].dest;
int weight = graph->edge[j].weight;
if (dist[u] != INT_MAX && dist[u] + weight < dist[v])
dist[v] = dist[u] + weight;
}
}
894
Chapter 124. Detect a negative cycle in a Graph (Bellman Ford)
// Step 3: check for negative-weight cycles.
// The above step guarantees shortest distances
// if graph doesn't contain negative weight cycle.
// If we get a shorter path, then there
// is a cycle.
for (int i = 0; i < E; i++) {
int u = graph->edge[i].src;
int v = graph->edge[i].dest;
int weight = graph->edge[i].weight;
if (dist[u] != INT_MAX && dist[u] + weight < dist[v])
return true;
}
return false;
}
// Driver program to test above functions
int main()
{
/* Let us create the graph given in above example */
int V = 5; // Number of vertices in graph
int E = 8; // Number of edges in graph
struct Graph* graph = createGraph(V, E);
// add edge 0-1 (or A-B in above figure)
graph->edge[0].src = 0;
graph->edge[0].dest = 1;
graph->edge[0].weight = -1;
// add edge 0-2 (or A-C in above figure)
graph->edge[1].src = 0;
graph->edge[1].dest = 2;
graph->edge[1].weight = 4;
// add edge 1-2 (or B-C in above figure)
graph->edge[2].src = 1;
graph->edge[2].dest = 2;
graph->edge[2].weight = 3;
// add edge 1-3 (or B-D in above figure)
graph->edge[3].src = 1;
graph->edge[3].dest = 3;
graph->edge[3].weight = 2;
// add edge 1-4 (or A-E in above figure)
graph->edge[4].src = 1;
graph->edge[4].dest = 4;
895
Chapter 124. Detect a negative cycle in a Graph (Bellman Ford)
graph->edge[4].weight = 2;
// add edge 3-2 (or D-C in above figure)
graph->edge[5].src = 3;
graph->edge[5].dest = 2;
graph->edge[5].weight = 5;
// add edge 3-1 (or D-B in above figure)
graph->edge[6].src = 3;
graph->edge[6].dest = 1;
graph->edge[6].weight = 1;
// add edge 4-3 (or E-D in above figure)
graph->edge[7].src = 4;
graph->edge[7].dest = 3;
graph->edge[7].weight = -3;
if (isNegCycleBellmanFord(graph, 0))
cout << "Yes";
else
cout << "No";
return 0;
}
Output :
No
896
Chapter 124. Detect a negative cycle in a Graph (Bellman Ford)
How to handle disconnected graph (If cycle is not reachable from source)?
The above algorithm and program might not work if the given graph is disconnected. It
works when all vertices are reachable from source vertex 0.
To handle disconnected graph, we can repeat the process for vertices for which distance is
infinite.
897
Chapter 124. Detect a negative cycle in a Graph (Bellman Ford)
898
Chapter 124. Detect a negative cycle in a Graph (Bellman Ford)
899
Chapter 124. Detect a negative cycle in a Graph (Bellman Ford)
900
Chapter 124. Detect a negative cycle in a Graph (Bellman Ford)
Output :
No
Source
https://www.geeksforgeeks.org/detect-negative-cycle-graph-bellman-ford/
901
Chapter 125
For a disconnected graph, we get the DFS forest as output. To detect cycle, we can check
for cycle in individual trees by checking back edges.
image
Image Source: http://www.cs.yale.edu/homes/aspnes/pinewiki/DepthFirstSearch.html
902
Chapter 125. Detect Cycle in a directed graph using colors
In the previous post, we have discussed a solution that stores visited vertices in a separate
array which stores vertices of current recursion call stack.
In this post a different solution is discussed. The solution is from CLRS book. The idea is
to do DFS of given graph and while doing traversal, assign one of the below three colors to
every vertex.
903
Chapter 125. Detect Cycle in a directed graph using colors
904
Chapter 125. Detect Cycle in a directed graph using colors
return false;
}
// Returns true if there is a cycle in graph
bool Graph::isCyclic()
{
// Initialize color of all vertices as WHITE
int *color = new int[V];
for (int i = 0; i < V; i++)
color[i] = WHITE;
// Do a DFS traversal beginning with all
// vertices
for (int i = 0; i < V; i++)
if (color[i] == WHITE)
if (DFSUtil(i, color) == true)
return true;
return false;
}
// Driver code to test above
int main()
{
// Create a graph given in the above diagram
Graph g(4);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 2);
g.addEdge(2, 0);
g.addEdge(2, 3);
g.addEdge(3, 3);
if (g.isCyclic())
cout << "Graph contains cycle";
else
cout << "Graph doesn't contain cycle";
return 0;
}
Python
905
Chapter 125. Detect Cycle in a directed graph using colors
class Graph():
def __init__(self, V):
self.V = V
self.graph = defaultdict(list)
def addEdge(self, u, v):
self.graph[u].append(v)
def DFSUtil(self, u, color):
# GRAY : This vertex is being processed (DFS
# for this vertex has started, but not
# ended (or this vertex is in function
# call stack)
color[u] = "GRAY"
for v in self.graph[u]:
if color[v] == "GRAY":
return True
if color[v] == "WHITE" and self.DFSUtil(v, color) == True:
return True
color[u] = "BLACK"
return False
def isCyclic(self):
color = ["WHITE"] * self.V
for i in range(self.V):
if color[i] == "WHITE":
if self.DFSUtil(i, color) == True:
return True
return False
# Driver program to test above functions
g = Graph(4)
g.addEdge(0, 1)
g.addEdge(0, 2)
g.addEdge(1, 2)
g.addEdge(2, 0)
g.addEdge(2, 3)
g.addEdge(3, 3)
print "Graph contains cycle" if g.isCyclic() == True\
else "Graph doesn't conatin cycle"
# This program is contributed by Divyanshu Mehta
906
Chapter 125. Detect Cycle in a directed graph using colors
Output :
Source
https://www.geeksforgeeks.org/detect-cycle-direct-graph-using-colors/
907
Chapter 126
We have discussed cycle detection for directed graph. We have also discussed a union-find
algorithm for cycle detection in undirected graphs.. The time complexity of the union-
find algorithm is O(ELogV). Like directed graphs, we can use DFSto detect cycle in an
undirected graph in O(V+E) time. We have discussed DFS based solution for cycle detection
in undirected graph.
In this article, BFS based solution is discussed. We do a BFS traversal of the given graph.
For every visited vertex ‘v’, if there is an adjacent ‘u’ such that u is already visited and u
is not parent of v, then there is a cycle in graph. If we don’t find such an adjacent for any
vertex, we say that there is no cycle. The assumption of this approach is that there are no
parallel edges between any two vertices.
We use a parent array to keep track of parent vertex for a vertex so that we do not consider
visited parent as cycle.
908
Chapter 126. Detect cycle in an undirected graph using BFS
// using BFS.
#include <bits/stdc++.h>
using namespace std;
void addEdge(vector<int> adj[], int u, int v)
{
adj[u].push_back(v);
adj[v].push_back(u);
}
bool isCyclicConntected(vector<int> adj[], int s,
int V, vector<bool>& visited)
{
// Set parent vertex for every vertex as -1.
vector<int> parent(V, -1);
// Create a queue for BFS
queue<int> q;
// Mark the current node as visited and enqueue it
visited[s] = true;
q.push(s);
while (!q.empty()) {
// Dequeue a vertex from queue and print it
int u = q.front();
q.pop();
// Get all adjacent vertices of the dequeued
// vertex s. If a adjacent has not been visited,
// then mark it visited and enqueue it. We also
// mark parent so that parent is not considered
// for cycle.
for (auto v : adj[u]) {
if (!visited[v]) {
visited[v] = true;
q.push(v);
parent[v] = u;
}
else if (parent[u] != v)
return true;
}
}
return false;
}
bool isCyclicDisconntected(vector<int> adj[], int V)
909
Chapter 126. Detect cycle in an undirected graph using BFS
{
// Mark all the vertices as not visited
vector<bool> visited(V, false);
for (int i = 0; i < V; i++)
if (!visited[i] && isCyclicConntected(adj, i,
V, visited))
return true;
return false;
}
// Driver program to test methods of graph class
int main()
{
int V = 4;
vector<int> adj[V];
addEdge(adj, 0, 1);
addEdge(adj, 1, 2);
addEdge(adj, 2, 0);
addEdge(adj, 2, 3);
if (isCyclicDisconntected(adj, V))
cout << "Yes";
else
cout << "No";
return 0;
}
Output :
Yes
Time Complexity: The program does a simple BFS Traversal of graph and graph is
represented using adjacency list. So the time complexity is O(V+E)
Source
https://www.geeksforgeeks.org/detect-cycle-in-an-undirected-graph-using-bfs/
910
Chapter 127
We have discussed cycle detection for directed graph. We have also discussed a union-find
algorithm for cycle detection in undirected graphs. The time complexity of the union-find
algorithm is O(ELogV). Like directed graphs, we can use DFSto detect cycle in an undirected
graph in O(V+E) time. We do a DFS traversal of the given graph. For every visited vertex
‘v’, if there is an adjacent ‘u’ such that u is already visited and u is not parent of v, then
there is a cycle in graph. If we don’t find such an adjacent for any vertex, we say that there
is no cycle. The assumption of this approach is that there are no parallel edges between any
two vertices.
C++
911
Chapter 127. Detect cycle in an undirected graph
912
Chapter 127. Detect cycle in an undirected graph
}
return false;
}
// Returns true if the graph contains a cycle, else false.
bool Graph::isCyclic()
{
// Mark all the vertices as not visited and not part of recursion
// stack
bool *visited = new bool[V];
for (int i = 0; i < V; i++)
visited[i] = false;
// Call the recursive helper function to detect cycle in different
// DFS trees
for (int u = 0; u < V; u++)
if (!visited[u]) // Don't recur for u if it is already visited
if (isCyclicUtil(u, visited, -1))
return true;
return false;
}
// Driver program to test above functions
int main()
{
Graph g1(5);
g1.addEdge(1, 0);
g1.addEdge(0, 2);
g1.addEdge(2, 0);
g1.addEdge(0, 3);
g1.addEdge(3, 4);
g1.isCyclic()? cout << "Graph contains cycle\n":
cout << "Graph doesn't contain cycle\n";
Graph g2(3);
g2.addEdge(0, 1);
g2.addEdge(1, 2);
g2.isCyclic()? cout << "Graph contains cycle\n":
cout << "Graph doesn't contain cycle\n";
return 0;
}
Java
913
Chapter 127. Detect cycle in an undirected graph
import java.util.*;
// This class represents a directed graph using adjacency list
// representation
class Graph
{
private int V; // No. of vertices
private LinkedList<Integer> adj[]; // Adjacency List Represntation
// Constructor
Graph(int v) {
V = v;
adj = new LinkedList[v];
for(int i=0; i<v; ++i)
adj[i] = new LinkedList();
}
// Function to add an edge into the graph
void addEdge(int v,int w) {
adj[v].add(w);
adj[w].add(v);
}
// A recursive function that uses visited[] and parent to detect
// cycle in subgraph reachable from vertex v.
Boolean isCyclicUtil(int v, Boolean visited[], int parent)
{
// Mark the current node as visited
visited[v] = true;
Integer i;
// Recur for all the vertices adjacent to this vertex
Iterator<Integer> it = adj[v].iterator();
while (it.hasNext())
{
i = it.next();
// If an adjacent is not visited, then recur for that
// adjacent
if (!visited[i])
{
if (isCyclicUtil(i, visited, v))
return true;
}
// If an adjacent is visited and not parent of current
// vertex, then there is a cycle.
else if (i != parent)
914
Chapter 127. Detect cycle in an undirected graph
return true;
}
return false;
}
// Returns true if the graph contains a cycle, else false.
Boolean isCyclic()
{
// Mark all the vertices as not visited and not part of
// recursion stack
Boolean visited[] = new Boolean[V];
for (int i = 0; i < V; i++)
visited[i] = false;
// Call the recursive helper function to detect cycle in
// different DFS trees
for (int u = 0; u < V; u++)
if (!visited[u]) // Don't recur for u if already visited
if (isCyclicUtil(u, visited, -1))
return true;
return false;
}
// Driver method to test above methods
public static void main(String args[])
{
// Create a graph given in the above diagram
Graph g1 = new Graph(5);
g1.addEdge(1, 0);
g1.addEdge(0, 2);
g1.addEdge(2, 0);
g1.addEdge(0, 3);
g1.addEdge(3, 4);
if (g1.isCyclic())
System.out.println("Graph contains cycle");
else
System.out.println("Graph doesn't contains cycle");
Graph g2 = new Graph(3);
g2.addEdge(0, 1);
g2.addEdge(1, 2);
if (g2.isCyclic())
System.out.println("Graph contains cycle");
else
System.out.println("Graph doesn't contains cycle");
}
915
Chapter 127. Detect cycle in an undirected graph
}
// This code is contributed by Aakash Hasija
Python
916
Chapter 127. Detect cycle in an undirected graph
#DFS trees
for i in range(self.V):
if visited[i] ==False: #Don't recur for u if it is already visited
if(self.isCyclicUtil(i,visited,-1))== True:
return True
return False
# Create a graph given in the above diagram
g = Graph(5)
g.addEdge(1, 0)
g.addEdge(0, 2)
g.addEdge(2, 0)
g.addEdge(0, 3)
g.addEdge(3, 4)
if g.isCyclic():
print "Graph contains cycle"
else :
print "Graph does not contain cycle "
g1 = Graph(3)
g1.addEdge(0,1)
g1.addEdge(1,2)
if g1.isCyclic():
print "Graph contains cycle"
else :
print "Graph does not contain cycle "
#This code is contributed by Neelam Yadav
Output:
Time Complexity: The program does a simple DFS Traversal of graph and graph is
represented using adjacency list. So the time complexity is O(V+E)
Exercise: Can we use BFS to detect cycle in an undirected graph in O(V+E) time? What
about directed graphs?
Source
https://www.geeksforgeeks.org/detect-cycle-undirected-graph/
917
Chapter 128
918
Chapter 128. Detecting negative cycle using Floyd Warshall
Negative weights are found in various applications of graphs. For example, instead of paying
cost for a path, we may get some advantage if we follow the path.
Examples:
Input : 4 4
0 1 1
1 2 -1
2 3 -1
3 0 -1
Output : Yes
The graph contains a negative cycle.
We have discussed Bellman Ford Algorithm based solution for this problem.
In this post, Floyd Warshall Algorithm based solution is discussed that works for both
connected and disconnected graphs.
Distance of any node from itself is always zero. But in some cases, as in this example, when
we traverse further from 4 to 1, the distance comes out to be -2, i.e. distance of 1 from 1
will become -2. This is our catch, we just have to check the nodes distance from itself and
if it comes out to be negative, we will detect the required negative cycle.
C++
919
Chapter 128. Detecting negative cycle using Floyd Warshall
920
Chapter 128. Detecting negative cycle using Floyd Warshall
int main()
{
/* Let us create the following weighted graph
1
(0)----------->(1)
/|\ |
| |
-1 | | -1
| \|/
(3)<-----------(2)
-1 */
int graph[V][V] = { {0 , 1 , INF , INF},
{INF , 0 , -1 , INF},
{INF , INF , 0 , -1},
{-1 , INF , INF , 0}};
if (negCyclefloydWarshall(graph))
cout << "Yes";
else
cout << "No";
return 0;
}
Java
921
Chapter 128. Detecting negative cycle using Floyd Warshall
/* Initialize the solution matrix same as input
graph matrix. Or we can say the initial values
of shortest distances are based on shortest
paths considering no intermediate vertex. */
for (i = 0; i < V; i++)
for (j = 0; j < V; j++)
dist[i][j] = graph[i][j];
/* Add all vertices one by one to the set of
intermediate vertices.
---> Before start of a iteration, we have shortest
distances between all pairs of vertices such
that the shortest distances consider only the
vertices in set {0, 1, 2, .. k-1} as intermediate
vertices.
----> After the end of a iteration, vertex no. k is
added to the set of intermediate vertices and
the set becomes {0, 1, 2, .. k} */
for (k = 0; k < V; k++)
{
// Pick all vertices as source one by one
for (i = 0; i < V; i++)
{
// Pick all vertices as destination for the
// above picked source
for (j = 0; j < V; j++)
{
// If vertex k is on the shortest path from
// i to j, then update the value of dist[i][j]
if (dist[i][k] + dist[k][j] < dist[i][j])
dist[i][j] = dist[i][k] + dist[k][j];
}
}
}
// If distance of any verex from itself
// becomes negative, then there is a negative
// weight cycle.
for (i = 0; i < V; i++)
if (dist[i][i] < 0)
return true;
return false;
}
922
Chapter 128. Detecting negative cycle using Floyd Warshall
// Driver code
public static void main (String[] args)
{
/* Let us create the following weighted graph
1
(0)----------->(1)
/|\ |
| |
-1 | | -1
| \|/
(3)<-----------(2)
-1 */
int graph[][] = { {0, 1, INF, INF},
{INF, 0, -1, INF},
{INF, INF, 0, -1},
{-1, INF, INF, 0}};
if (negCyclefloydWarshall(graph))
System.out.print("Yes");
else
System.out.print("No");
}
}
// This code is contributed by Anant Agarwal.
Python3
923
Chapter 128. Detecting negative cycle using Floyd Warshall
# Returns true if graph has
# negative weight cycle
# else false.
def negCyclefloydWarshall(graph):
# dist[][] will be the
# output matrix that will
# finally have the shortest
# distances between every
# pair of vertices
dist=[[0 for i in range(V+1)]for j in range(V+1)]
# Initialize the solution
# matrix same as input
# graph matrix. Or we can
# say the initial values
# of shortest distances
# are based on shortest
# paths considering no
# intermediate vertex.
for i in range(V):
for j in range(V):
dist[i][j] = graph[i][j]
''' Add all vertices one
by one to the set of
intermediate vertices.
---> Before start of a iteration,
we have shortest
distances between all pairs
of vertices such
that the shortest distances
consider only the
vertices in set {0, 1, 2, .. k-1}
as intermediate vertices.
----> After the end of a iteration,
vertex no. k is
added to the set of
intermediate vertices and
the set becomes {0, 1, 2, .. k} '''
for k in range(V):
# Pick all vertices
# as source one by one
for i in range(V):
# Pick all vertices as
924
Chapter 128. Detecting negative cycle using Floyd Warshall
925
Chapter 128. Detecting negative cycle using Floyd Warshall
# by Anant Agarwal.
C#
926
Chapter 128. Detecting negative cycle using Floyd Warshall
927
Chapter 128. Detecting negative cycle using Floyd Warshall
int [,]graph = { {0, 1, INF, INF},
{INF, 0, -1, INF},
{INF, INF, 0, -1},
{-1, INF, INF, 0}};
if (negCyclefloydWarshall(graph))
Console.Write("Yes");
else
Console.Write("No");
}
}
}
// This code is contributed by Sam007.
Output:
Yes
Source
https://www.geeksforgeeks.org/detecting-negative-cycle-using-floyd-warshall/
928
Chapter 129
Input :
v1 -> v2 (implies vertex 1 is connected to vertex 2)
v3 -> v2
v4 -> v2
v5 -> v2
v6 -> v2
Output :
Sink found at vertex 2
Input :
v1 -> v6
v2 -> v3
v2 -> v4
v4 -> v3
v5 -> v3
Output :
No Sink
We try to eliminate n – 1 non-sink vertices in O(n) time and check the remaining vertex
for the sink property.
To eliminate vertices, we check whether a particular index (A[i][j]) in the adjacency matrix
is a 1 or a 0. If it is a 0, it means that the vertex corresponding to index j cannot be a
sink. If the index is a 1, it means the vertex corresponding to i cannot be a sink. We keep
929
Chapter 129. Determine whether a universal sink exists in a directed graph
increasing i and j in this fashion until either i or j exceeds the number of vertices.
Using this method allows us to carry out the universal sink test for only one vertex instead
of all n vertices. Suppose we are left with only vertex i.
We now check for whether row i has only 0s and whether row j as only 1s except for A[i][i],
which will be 0.
Illustration :
v1 -> v2
v3 -> v2
v4 -> v2
v5 -> v2
v6 -> v2
We can visualize the adjacency matrix for
the above as follows:
0 1 0 0 0 0
0 0 0 0 0 0
0 1 0 0 0 0
0 1 0 0 0 0
0 1 0 0 0 0
We observe that vertex 2 does not have any emanating edge, and that every other vertex
has an edge in vertex 2. At A[0][0] (A[i][j]), we encounter a 0, so we increment j and next
look at A[0][1]. Here we encounter a 1. So we have to increment i by 1. A[1][1] is 0, so we
keep increasing j. We notice that A[1][2], A[1][3].. etc are all 0, so j will exceed the
number of vertices (6 in this example). We now check row i and column i for the sink
property. Row i must be completely 0, and column i must be completely 1 except for the
index A[i][i]
930
Chapter 129. Determine whether a universal sink exists in a directed graph
Adjacency Matrix
Second Example:
v1 -> v6
v2 -> v3
v2 -> v4
v4 -> v3
v5 -> v3
We can visualize the adjacency matrix
for the above as follows:
0 0 0 0 0 1
0 0 1 1 0 0
0 0 0 0 0 0
0 0 1 0 0 0
0 0 1 0 0 0
0 0 0 0 0 0
In this example, we observer that in row 1, every element is 0 except for the last column.
So we will increment j until we reach the 1. When we reach 1, we increment i as long as
the value of A[i][j] is 0. If i exceeds the number of vertices, it is not possible to have a sink,
and in this case, i will exceed the number of vertices.
Adjacency Matrix
931
Chapter 129. Determine whether a universal sink exists in a directed graph
class Graph
{
int vertices;
int[][] adjacency_matrix;
// constructor to initialize number of vertices and
// size of adjacency matrix
public graph(int vertices)
{
this.vertices = vertices;
adjacency_matrix = new int[vertices][vertices];
}
public void insert(int source, int destination)
{
// make adjacency_matrix[i][j] = 1 if there is
// an edge from i to j
adjacency_matrix[destination-1] = 1;
}
public boolean issink(int i)
{
for (int j = 0 ; j < vertices ; j++)
{
// if any element in the row i is 1, it means
// that there is an edge emanating from the
// vertex, which means it cannot be a sink
if (adjacency_matrix[i][j] == 1)
return false;
// if any element other than i in the column
// i is 0, it means that there is no edge from
// that vertex to the vertex we are testing
// and hence it cannot be a sink
if (adjacency_matrix[j][i] == 0 && j != i)
return false;
}
//if none of the checks fails, return true
return true;
}
// we will eliminate n-1 non sink vertices so that
// we have to check for only one vertex instead of
// all n vertices
public int eliminate()
{
int i = 0, j = 0;
while (i < vertices && j < vertices)
932
Chapter 129. Determine whether a universal sink exists in a directed graph
{
// If the index is 1, increment the row we are
// checking by 1
// else increment the column
if (adjacency_matrix[i][j] == 1)
i = i + 1;
else
j = j + 1;
}
// If i exceeds the number of vertices, it
// means that there is no valid vertex in
// the given vertices that can be a sink
if (i > vertices)
return -1;
else if (!issink(i))
return -1;
else return i;
}
}
public class Sink
{
public static void main(String[] args)throws IOException
{
int number_of_vertices = 6;
int number_of_edges = 5;
graph g = new graph(number_of_vertices);
/*
//input set 1
g.insert(1, 6);
g.insert(2, 6);
g.insert(3, 6);
g.insert(4, 6);
g.insert(5, 6);
*/
//input set 2
g.insert(1, 6);
g.insert(2, 3);
g.insert(2, 4);
g.insert(4, 3);
g.insert(5, 3);
int vertex = g.eliminate();
// returns 0 based indexing of vertex. returns
// -1 if no sink exits.
933
Chapter 129. Determine whether a universal sink exists in a directed graph
Output:
input set 1:
Sink found at vertex 6
input set 2:
No Sink
This program eliminates non-sink vertices in O(n) complexity and checks for the sink prop-
erty in O(n) complexity.
You may also try The Celebrity Problem, which is an application of this concept
Source
https://www.geeksforgeeks.org/determine-whether-universal-sink-exists-directed-graph/
934
Chapter 130
DFS for a n-ary tree (acyclic graph) represented as adjacency list - GeeksforGeeks
A tree consisting of n nodes is given, we need to print its DFS.
Examples :
935
Chapter 130. DFS for a n-ary tree (acyclic graph) represented as adjacency list
{
// Printing traversed node
cout << node << '\n';
// Traversing adjacent edges
for (int i = 0; i < list[node].size(); i++) {
// Not traversing the parent node
if (list[node][i] != arrival)
dfs(list, list[node][i], node);
}
}
int main()
{
// Number of nodes
int nodes = 5;
// Adjacency list
vector<int> list[10000];
// Designing the tree
list[1].push_back(2);
list[2].push_back(1);
list[1].push_back(3);
list[3].push_back(1);
list[2].push_back(4);
list[4].push_back(2);
list[3].push_back(5);
list[5].push_back(3);
// Function call
dfs(list, 1, 0);
return 0;
}
Java
936
Chapter 130. DFS for a n-ary tree (acyclic graph) represented as adjacency list
937
Chapter 130. DFS for a n-ary tree (acyclic graph) represented as adjacency list
}
// This code is contributed by Arnav Kr. Mandal.
Output:
1
2
4
3
5
Source
https://www.geeksforgeeks.org/dfs-n-ary-tree-acyclic-graph-represented-adjacency-list/
938
Chapter 131
Can we optimize Dijkstra’s shortest path algorithm to work better than O(E
log V) if maximum weight is small (or range of edge weights is small)?
For example, in the above diagram, maximum weight is 14. Many a times the range of
weights on edges in is in small range (i.e. all edge weight can be mapped to 0, 1, 2.. w
where w is a small number). In that case, Dijkstra’s algorithm can be modified by using
different data structure, buckets, which is called dial implementation of dijkstra’s algorithm.
939
Chapter 131. Dial’s Algorithm (Optimized Dijkstra for small range weights)
time complexity is O(E + WV) where W is maximum weight on any edge of graph, so
we can see that, if W is small then this implementation runs much faster than traditional
algorithm. Following are important observations.
• Maximum distance between any two node can be at max w(V – 1) (w is maximum
edge weight and we can have at max V-1 edges between two vertices).
• In Dijkstra algorithm, distances are finalized in non-decreasing, i.e., distance of the
closer (to given source) vertices is finalized before the distant vertices.
Algorithm
Below is complete algorithm:
Implementation
Since the maximum distance can be w(V – 1), we create wV buckets (more for simplicity of
code) for implementation of algorithm which can be large if w is big.
940
Chapter 131. Dial’s Algorithm (Optimized Dijkstra for small range weights)
941
Chapter 131. Dial’s Algorithm (Optimized Dijkstra for small range weights)
942
Chapter 131. Dial’s Algorithm (Optimized Dijkstra for small range weights)
// updating the distance
dist[v].first = du + weight;
dv = dist[v].first;
// pushing vertex v into updated distance's bucket
B[dv].push_front(v);
// storing updated iterator in dist[v].second
dist[v].second = B[dv].begin();
}
}
}
// Print shortest distances stored in dist[]
printf("Vertex Distance from Source\n");
for (int i = 0; i < V; ++i)
printf("%d %d\n", i, dist[i].first);
}
// Driver program to test methods of graph class
int main()
{
// create the graph given in above fugure
int V = 9;
Graph g(V);
// making above shown graph
g.addEdge(0, 1, 4);
g.addEdge(0, 7, 8);
g.addEdge(1, 2, 8);
g.addEdge(1, 7, 11);
g.addEdge(2, 3, 7);
g.addEdge(2, 8, 2);
g.addEdge(2, 5, 4);
g.addEdge(3, 4, 9);
g.addEdge(3, 5, 14);
g.addEdge(4, 5, 10);
g.addEdge(5, 6, 2);
g.addEdge(6, 7, 1);
g.addEdge(6, 8, 6);
g.addEdge(7, 8, 7);
// maximum weighted edge - 14
g.shortestPath(0, 14);
return 0;
}
943
Chapter 131. Dial’s Algorithm (Optimized Dijkstra for small range weights)
Output:
Illustration
Below is step by step illustration taken from here.
944
Chapter 131. Dial’s Algorithm (Optimized Dijkstra for small range weights)
945
Chapter 131. Dial’s Algorithm (Optimized Dijkstra for small range weights)
946
Chapter 131. Dial’s Algorithm (Optimized Dijkstra for small range weights)
947
Chapter 131. Dial’s Algorithm (Optimized Dijkstra for small range weights)
948
Chapter 131. Dial’s Algorithm (Optimized Dijkstra for small range weights)
949
Chapter 131. Dial’s Algorithm (Optimized Dijkstra for small range weights)
This article is contributed by Utkarsh Trivedi. Please write comments if you find anything
incorrect, or you want to share more information about the topic discussed above.
Source
https://www.geeksforgeeks.org/dials-algorithm-optimized-dijkstra-for-small-range-weights/
950
Chapter 132
951
Chapter 132. Dijkstra’s Algorithm for Adjacency List Representation Greedy Algo-8
distance value is more than weight of u-v plus distance value of u, then update the distance
value of v.
Let us understand with the following example. Let the given source vertex be 0
Initially, distance value of source vertex is 0 and INF (infinite) for all other vertices. So
source vertex is extracted from Min Heap and distance values of vertices adjacent to 0 (1
and 7) are updated. Min Heap contains all vertices except vertex 0.
The vertices in green color are the vertices for which minimum distances are finalized and
are not in Min Heap
Since distance value of vertex 1 is minimum among all nodes in Min Heap, it is extracted from
Min Heap and distance values of vertices adjacent to 1 are updated (distance is updated if
the a vertex is not in Min Heap and distance through 1 is shorter than the previous distance).
Min Heap contains all vertices except vertex 0 and 1.
Pick the vertex with minimum distance value from min heap. Vertex 7 is picked. So min
heap now contains all vertices except 0, 1 and 7. Update the distance values of adjacent
vertices of 7. The distance value of vertex 6 and 8 becomes finite (15 and 9 respectively).
952
Chapter 132. Dijkstra’s Algorithm for Adjacency List Representation Greedy Algo-8
Pick the vertex with minimum distance from min heap. Vertex 6 is picked. So min heap now
contains all vertices except 0, 1, 7 and 6. Update the distance values of adjacent vertices of
6. The distance value of vertex 5 and 8 are updated.
Above steps are repeated till min heap doesn’t become empty. Finally, we get the following
shortest path tree.
C++
953
Chapter 132. Dijkstra’s Algorithm for Adjacency List Representation Greedy Algo-8
};
// A structure to represent an adjacency liat
struct AdjList
{
struct AdjListNode *head; // pointer to head node of list
};
// A structure to represent a graph. A graph is an array of adjacency lists.
// Size of array will be V (number of vertices in graph)
struct Graph
{
int V;
struct AdjList* array;
};
// A utility function to create a new adjacency list node
struct AdjListNode* newAdjListNode(int dest, int weight)
{
struct AdjListNode* newNode =
(struct AdjListNode*) malloc(sizeof(struct AdjListNode));
newNode->dest = dest;
newNode->weight = weight;
newNode->next = NULL;
return newNode;
}
// A utility function that creates a graph of V vertices
struct Graph* createGraph(int V)
{
struct Graph* graph = (struct Graph*) malloc(sizeof(struct Graph));
graph->V = V;
// Create an array of adjacency lists. Size of array will be V
graph->array = (struct AdjList*) malloc(V * sizeof(struct AdjList));
// Initialize each adjacency list as empty by making head as NULL
for (int i = 0; i < V; ++i)
graph->array[i].head = NULL;
return graph;
}
// Adds an edge to an undirected graph
void addEdge(struct Graph* graph, int src, int dest, int weight)
{
// Add an edge from src to dest. A new node is added to the adjacency
// list of src. The node is added at the begining
954
Chapter 132. Dijkstra’s Algorithm for Adjacency List Representation Greedy Algo-8
955
Chapter 132. Dijkstra’s Algorithm for Adjacency List Representation Greedy Algo-8
// A utility function to swap two nodes of min heap. Needed for min heapify
void swapMinHeapNode(struct MinHeapNode** a, struct MinHeapNode** b)
{
struct MinHeapNode* t = *a;
*a = *b;
*b = t;
}
// A standard function to heapify at given idx
// This function also updates position of nodes when they are swapped.
// Position is needed for decreaseKey()
void minHeapify(struct MinHeap* minHeap, int idx)
{
int smallest, left, right;
smallest = idx;
left = 2 * idx + 1;
right = 2 * idx + 2;
if (left < minHeap->size &&
minHeap->array[left]->dist < minHeap->array[smallest]->dist )
smallest = left;
if (right < minHeap->size &&
minHeap->array[right]->dist < minHeap->array[smallest]->dist )
smallest = right;
if (smallest != idx)
{
// The nodes to be swapped in min heap
MinHeapNode *smallestNode = minHeap->array[smallest];
MinHeapNode *idxNode = minHeap->array[idx];
// Swap positions
minHeap->pos[smallestNode->v] = idx;
minHeap->pos[idxNode->v] = smallest;
// Swap nodes
swapMinHeapNode(&minHeap->array[smallest], &minHeap->array[idx]);
minHeapify(minHeap, smallest);
}
}
// A utility function to check if the given minHeap is ampty or not
int isEmpty(struct MinHeap* minHeap)
{
return minHeap->size == 0;
956
Chapter 132. Dijkstra’s Algorithm for Adjacency List Representation Greedy Algo-8
}
// Standard function to extract minimum node from heap
struct MinHeapNode* extractMin(struct MinHeap* minHeap)
{
if (isEmpty(minHeap))
return NULL;
// Store the root node
struct MinHeapNode* root = minHeap->array[0];
// Replace root node with last node
struct MinHeapNode* lastNode = minHeap->array[minHeap->size - 1];
minHeap->array[0] = lastNode;
// Update position of last node
minHeap->pos[root->v] = minHeap->size-1;
minHeap->pos[lastNode->v] = 0;
// Reduce heap size and heapify root
--minHeap->size;
minHeapify(minHeap, 0);
return root;
}
// Function to decreasy dist value of a given vertex v. This function
// uses pos[] of min heap to get the current index of node in min heap
void decreaseKey(struct MinHeap* minHeap, int v, int dist)
{
// Get the index of v in heap array
int i = minHeap->pos[v];
// Get the node and update its dist value
minHeap->array[i]->dist = dist;
// Travel up while the complete tree is not hepified.
// This is a O(Logn) loop
while (i && minHeap->array[i]->dist < minHeap->array[(i - 1) / 2]->dist)
{
// Swap this node with its parent
minHeap->pos[minHeap->array[i]->v] = (i-1)/2;
minHeap->pos[minHeap->array[(i-1)/2]->v] = i;
swapMinHeapNode(&minHeap->array[i], &minHeap->array[(i - 1) / 2]);
// move to parent index
i = (i - 1) / 2;
}
957
Chapter 132. Dijkstra’s Algorithm for Adjacency List Representation Greedy Algo-8
}
// A utility function to check if a given vertex
// 'v' is in min heap or not
bool isInMinHeap(struct MinHeap *minHeap, int v)
{
if (minHeap->pos[v] < minHeap->size)
return true;
return false;
}
// A utility function used to print the solution
void printArr(int dist[], int n)
{
printf("Vertex Distance from Source\n");
for (int i = 0; i < n; ++i)
printf("%d \t\t %d\n", i, dist[i]);
}
// The main function that calulates distances of shortest paths from src to all
// vertices. It is a O(ELogV) function
void dijkstra(struct Graph* graph, int src)
{
int V = graph->V;// Get the number of vertices in graph
int dist[V]; // dist values used to pick minimum weight edge in cut
// minHeap represents set E
struct MinHeap* minHeap = createMinHeap(V);
// Initialize min heap with all vertices. dist value of all vertices
for (int v = 0; v < V; ++v)
{
dist[v] = INT_MAX;
minHeap->array[v] = newMinHeapNode(v, dist[v]);
minHeap->pos[v] = v;
}
// Make dist value of src vertex as 0 so that it is extracted first
minHeap->array[src] = newMinHeapNode(src, dist[src]);
minHeap->pos[src] = src;
dist[src] = 0;
decreaseKey(minHeap, src, dist[src]);
// Initially size of min heap is equal to V
minHeap->size = V;
// In the followin loop, min heap contains all nodes
// whose shortest distance is not yet finalized.
958
Chapter 132. Dijkstra’s Algorithm for Adjacency List Representation Greedy Algo-8
while (!isEmpty(minHeap))
{
// Extract the vertex with minimum distance value
struct MinHeapNode* minHeapNode = extractMin(minHeap);
int u = minHeapNode->v; // Store the extracted vertex number
// Traverse through all adjacent vertices of u (the extracted
// vertex) and update their distance values
struct AdjListNode* pCrawl = graph->array[u].head;
while (pCrawl != NULL)
{
int v = pCrawl->dest;
// If shortest distance to v is not finalized yet, and distance to v
// through u is less than its previously calculated distance
if (isInMinHeap(minHeap, v) && dist[u] != INT_MAX &&
pCrawl->weight + dist[u] < dist[v])
{
dist[v] = dist[u] + pCrawl->weight;
// update distance value in min heap also
decreaseKey(minHeap, v, dist[v]);
}
pCrawl = pCrawl->next;
}
}
// print the calculated shortest distances
printArr(dist, V);
}
// Driver program to test above functions
int main()
{
// create the graph given in above fugure
int V = 9;
struct Graph* graph = createGraph(V);
addEdge(graph, 0, 1, 4);
addEdge(graph, 0, 7, 8);
addEdge(graph, 1, 2, 8);
addEdge(graph, 1, 7, 11);
addEdge(graph, 2, 3, 7);
addEdge(graph, 2, 8, 2);
addEdge(graph, 2, 5, 4);
addEdge(graph, 3, 4, 9);
addEdge(graph, 3, 5, 14);
addEdge(graph, 4, 5, 10);
959
Chapter 132. Dijkstra’s Algorithm for Adjacency List Representation Greedy Algo-8
addEdge(graph, 5, 6, 2);
addEdge(graph, 6, 7, 1);
addEdge(graph, 6, 8, 6);
addEdge(graph, 7, 8, 7);
dijkstra(graph, 0);
return 0;
}
Python
960
Chapter 132. Dijkstra’s Algorithm for Adjacency List Representation Greedy Algo-8
smallest = left
if right < self.size and self.array[right][1]\
< self.array[smallest][1]:
smallest = right
# The nodes to be swapped in min
# heap if idx is not smallest
if smallest != idx:
# Swap positions
self.pos[ self.array[smallest][0] ] = idx
self.pos[ self.array[idx][0] ] = smallest
# Swap nodes
self.swapMinHeapNode(smallest, idx)
self.minHeapify(smallest)
# Standard function to extract minimum
# node from heap
def extractMin(self):
# Return NULL wif heap is empty
if self.isEmpty() == True:
return
# Store the root node
root = self.array[0]
# Replace root node with last node
lastNode = self.array[self.size - 1]
self.array[0] = lastNode
# Update position of last node
self.pos[lastNode[0]] = 0
self.pos[root[0]] = self.size - 1
# Reduce heap size and heapify root
self.size -= 1
self.minHeapify(0)
return root
def isEmpty(self):
return True if self.size == 0 else False
def decreaseKey(self, v, dist):
961
Chapter 132. Dijkstra’s Algorithm for Adjacency List Representation Greedy Algo-8
# Get the index of v in heap array
i = self.pos[v]
# Get the node and update its dist value
self.array[i][1] = dist
# Travel up while the complete tree is
# not hepified. This is a O(Logn) loop
while i > 0 and self.array[i][1] < self.array[(i - 1) / 2][1]:
# Swap this node with its parent
self.pos[ self.array[i][0] ] = (i-1)/2
self.pos[ self.array[(i-1)/2][0] ] = i
self.swapMinHeapNode(i, (i - 1)/2 )
# move to parent index
i = (i - 1) / 2;
# A utility function to check if a given
# vertex 'v' is in min heap or not
def isInMinHeap(self, v):
if self.pos[v] < self.size:
return True
return False
def printArr(dist, n):
print "Vertex\tDistance from source"
for i in range(n):
print "%d\t\t%d" % (i,dist[i])
class Graph():
def __init__(self, V):
self.V = V
self.graph = defaultdict(list)
# Adds an edge to an undirected graph
def addEdge(self, src, dest, weight):
# Add an edge from src to dest. A new node
# is added to the adjacency list of src. The
# node is added at the begining. The first
# element of the node has the destination
962
Chapter 132. Dijkstra’s Algorithm for Adjacency List Representation Greedy Algo-8
963
Chapter 132. Dijkstra’s Algorithm for Adjacency List Representation Greedy Algo-8
Output:
964
Chapter 132. Dijkstra’s Algorithm for Adjacency List Representation Greedy Algo-8
7 8
8 14
Time Complexity: The time complexity of the above code/algorithm looks O(V^2) as
there are two nested while loops. If we take a closer look, we can observe that the statements
in inner loop are executed O(V+E) times (similar to BFS). The inner loop has decreaseKey()
operation which takes O(LogV) time. So overall time complexity is O(E+V)*O(LogV) which
is O((E+V)*LogV) = O(ELogV)
Note that the above code uses Binary Heap for Priority Queue implementation. Time com-
plexity can be reduced to O(E + VLogV) using Fibonacci Heap. The reason is, Fibonacci
Heap takes O(1) time for decrease-key operation while Binary Heap takes O(Logn) time.
Notes:
1) The code calculates shortest distance, but doesn’t calculate the path information. We
can create a parent array, update the parent array when distance is updated (like prim’s
implementation) and use it show the shortest path from source to different vertices.
2) The code is for undirected graph, same dijekstra function can be used for directed graphs
also.
3) The code finds shortest distances from source to all vertices. If we are interested only in
shortest distance from source to a single target, we can break the for loop when the picked
minimum distance vertex is equal to target (Step 3.a of algorithm).
4) Dijkstra’s algorithm doesn’t work for graphs with negative weight edges. For graphs with
negative weight edges, Bellman–Ford algorithm can be used, we will soon be discussing it
as a separate post.
Printing Paths in Dijkstra’s Shortest Path Algorithm
Dijkstra’s shortest path algorithm using set in STL
References:
Introduction to Algorithms by Clifford Stein, Thomas H. Cormen, Charles E. Leiserson,
Ronald L.
Algorithms by Sanjoy Dasgupta, Christos Papadimitriou, Umesh Vazirani
Source
https://www.geeksforgeeks.org/dijkstras-algorithm-for-adjacency-list-representation-greedy-algo-8/
965
Chapter 133
Input : Source = 0
Output :
Vertex Distance from Source
0 0
1 4
2 12
3 19
4 21
5 11
6 9
7 8
8 14
• Dijkstra’s Algorithm for Adjacency Matrix Representation (In C/C++ with time com-
plexity O(v2 )
• Dijkstra’s Algorithm for Adjacency List Representation (In C with Time Complexity
O(ELogV))
966
Chapter 133. Dijkstra’s Shortest Path Algorithm using priority_queue of STL
• Dijkstra’s shortest path algorithm using set in STL (In C++ with Time Complexity
O(ELogV))
The second implementation is time complexity wise better, but is really complex as we have
implemented our own priority queue.
The Third implementation is simpler as it uses STL. The issue with third implementation is,
it uses set which in turn uses Self-Balancing Binary Search Trees. For Dijkstra’s algorithm,
it is always recommended to use heap (or priority queue) as the required operations (extract
minimum and decrease key) match with speciality of heap (or priority queue). However, the
problem is, priority_queue doesn’t support decrease key. To resolve this problem, do not
update a key, but insert one more copy of it. So we allow multiple instances of same vertex
in priority queue. This approach doesn’t require decrease key operation and has below
important properties.
967
Chapter 133. Dijkstra’s Shortest Path Algorithm using priority_queue of STL
968
Chapter 133. Dijkstra’s Shortest Path Algorithm using priority_queue of STL
}
// Prints shortest paths from src to all other vertices
void Graph::shortestPath(int src)
{
// Create a priority queue to store vertices that
// are being preprocessed. This is weird syntax in C++.
// Refer below link for details of this syntax
// https://www.geeksforgeeks.org/implement-min-heap-using-stl/
priority_queue< iPair, vector <iPair> , greater<iPair> > pq;
// Create a vector for distances and initialize all
// distances as infinite (INF)
vector<int> dist(V, INF);
// Insert source itself in priority queue and initialize
// its distance as 0.
pq.push(make_pair(0, src));
dist[src] = 0;
/* Looping till priority queue becomes empty (or all
distances are not finalized) */
while (!pq.empty())
{
// The first vertex in pair is the minimum distance
// vertex, extract it from priority queue.
// vertex label is stored in second of pair (it
// has to be done this way to keep the vertices
// sorted distance (distance must be first item
// in pair)
int u = pq.top().second;
pq.pop();
// 'i' is used to get all adjacent vertices of a vertex
list< pair<int, int> >::iterator i;
for (i = adj[u].begin(); i != adj[u].end(); ++i)
{
// Get vertex label and weight of current adjacent
// of u.
int v = (*i).first;
int weight = (*i).second;
// If there is shorted path to v through u.
if (dist[v] > dist[u] + weight)
{
// Updating distance of v
dist[v] = dist[u] + weight;
pq.push(make_pair(dist[v], v));
969
Chapter 133. Dijkstra’s Shortest Path Algorithm using priority_queue of STL
}
}
}
// Print shortest distances stored in dist[]
printf("Vertex Distance from Source\n");
for (int i = 0; i < V; ++i)
printf("%d \t\t %d\n", i, dist[i]);
}
// Driver program to test methods of graph class
int main()
{
// create the graph given in above fugure
int V = 9;
Graph g(V);
// making above shown graph
g.addEdge(0, 1, 4);
g.addEdge(0, 7, 8);
g.addEdge(1, 2, 8);
g.addEdge(1, 7, 11);
g.addEdge(2, 3, 7);
g.addEdge(2, 8, 2);
g.addEdge(2, 5, 4);
g.addEdge(3, 4, 9);
g.addEdge(3, 5, 14);
g.addEdge(4, 5, 10);
g.addEdge(5, 6, 2);
g.addEdge(6, 7, 1);
g.addEdge(6, 8, 6);
g.addEdge(7, 8, 7);
g.shortestPath(0);
return 0;
}
Output:
970
Chapter 133. Dijkstra’s Shortest Path Algorithm using priority_queue of STL
4 21
5 11
6 9
7 8
8 14
971
Chapter 133. Dijkstra’s Shortest Path Algorithm using priority_queue of STL
{
// The first vertex in pair is the minimum distance
// vertex, extract it from priority queue.
// vertex label is stored in second of pair (it
// has to be done this way to keep the vertices
// sorted distance (distance must be first item
// in pair)
int u = pq.top().second;
pq.pop();
// Get all adjacent of u.
for (auto x : adj[u])
{
// Get vertex label and weight of current adjacent
// of u.
int v = x.first;
int weight = x.second;
// If there is shorted path to v through u.
if (dist[v] > dist[u] + weight)
{
// Updating distance of v
dist[v] = dist[u] + weight;
pq.push(make_pair(dist[v], v));
}
}
}
// Print shortest distances stored in dist[]
printf("Vertex Distance from Source\n");
for (int i = 0; i < V; ++i)
printf("%d \t\t %d\n", i, dist[i]);
}
// Driver program to test methods of graph class
int main()
{
int V = 9;
vector<iPair > adj[V];
// making above shown graph
addEdge(adj, 0, 1, 4);
addEdge(adj, 0, 7, 8);
addEdge(adj, 1, 2, 8);
addEdge(adj, 1, 7, 11);
addEdge(adj, 2, 3, 7);
addEdge(adj, 2, 8, 2);
addEdge(adj, 2, 5, 4);
972
Chapter 133. Dijkstra’s Shortest Path Algorithm using priority_queue of STL
addEdge(adj, 3, 4, 9);
addEdge(adj, 3, 5, 14);
addEdge(adj, 4, 5, 10);
addEdge(adj, 5, 6, 2);
addEdge(adj, 6, 7, 1);
addEdge(adj, 6, 8, 6);
addEdge(adj, 7, 8, 7);
shortestPath(adj, V, 0);
return 0;
}
Output:
Further Optimization
We can use a flag array to store what all vertices have been extracted from priority queue.
This way we can avoid updating weights of items that have already been extracted. Please
see this for optimized implementation.
This article is contributed by Shubham Agrawal. Please write comments if you find
anything incorrect, or you want to share more information about the topic discussed above
Source
https://www.geeksforgeeks.org/dijkstras-shortest-path-algorithm-using-priority_queue-stl/
973
Chapter 134
Input : Source = 0
Output :
Vertex Distance from Source
0 0
1 4
2 12
3 19
4 21
5 11
6 9
7 8
8 14
• Dijkstra’s Algorithm for Adjacency Matrix Representation (In C/C++ with time com-
plexity O(v2 )
• Dijkstra’s Algorithm for Adjacency List Representation (In C with Time Complexity
O(ELogV))
974
Chapter 134. Dijkstra’s shortest path algorithm using set in STL
The second implementation is time complexity wise better, but is really complex as we have
implemented our own priority queue. STL provides priority_queue, but the provided prior-
ity queue doesn’t support decrease key and delete operations. And in Dijkstra’s algorithm,
we need a priority queue and below operations on priority queue :
• ExtractMin : from all those vertices whose shortest distance is not yet found, we need
to get vertex with minimum distance.
Above operations can be easily implemented by set data structure of c++ STL, set keeps
all its keys in sorted order so minimum distant vertex will always be at beginning, we can
extract it from there, which is the ExtractMin operation and update other adjacent vertex
accordingly if any vetex’s distance become smaller then delete its previous entry and insert
new updated entry which is DecreaseKey operation.
Below is algorithm based on set data structure.
975
Chapter 134. Dijkstra’s shortest path algorithm using set in STL
976
Chapter 134. Dijkstra’s shortest path algorithm using set in STL
977
Chapter 134. Dijkstra’s shortest path algorithm using set in STL
Output :
978
Chapter 134. Dijkstra’s shortest path algorithm using set in STL
4 21
5 11
6 9
7 8
8 14
Time Complexity : Set in C++ are typically implemented using Self-balancing binary
search trees. Therefore, time complexity of set operations like insert, delete is logarithmic
and time complexity of above solution is O(ELogV)).
This article is contributed by Utkarsh Trivedi. Please write comments if you find
anything incorrect, or you want to share more information about the topic discussed above
Source
https://www.geeksforgeeks.org/dijkstras-shortest-path-algorithm-using-set-in-stl/
979
Chapter 135
Dijsktra’s algorithm
Given a graph and a source vertex in the graph, find shortest paths from source to all
vertices in the given graph.
Dijkstra’s algorithm is very similar to Prim’s algorithm for minimum spanning tree. Like
Prim’s MST, we generate a SPT (shortest path tree) with given source as root. We maintain
two sets, one set contains vertices included in shortest path tree, other set includes vertices
not yet included in shortest path tree. At every step of the algorithm, we find a vertex
which is in the other set (set of not yet included) and has a minimum distance from the
source.
Below are the detailed steps used in Dijkstra’s algorithm to find the shortest path from a
single source vertex to all other vertices in the given graph.
Algorithm
1) Create a set sptSet (shortest path tree set) that keeps track of vertices included in shortest
path tree, i.e., whose minimum distance from source is calculated and finalized. Initially,
this set is empty.
2) Assign a distance value to all vertices in the input graph. Initialize all distance values as
INFINITE. Assign distance value as 0 for the source vertex so that it is picked first.
3) While sptSet doesn’t include all vertices
….a) Pick a vertex u which is not there in sptSet and has minimum distance value.
….b) Include u to sptSet.
….c) Update distance value of all adjacent vertices of u. To update the distance values,
iterate through all adjacent vertices. For every adjacent vertex v, if sum of distance value
of u (from source) and weight of edge u-v, is less than the distance value of v, then update
the distance value of v.
Let us understand with the following example:
980
Chapter 135. Dijkstra’s shortest path algorithm Greedy Algo-7
The set sptSet is initially empty and distances assigned to vertices are {0, INF, INF, INF,
INF, INF, INF, INF} where INF indicates infinite. Now pick the vertex with minimum
distance value. The vertex 0 is picked, include it in sptSet. So sptSet becomes {0}. After
including 0 to sptSet, update distance values of its adjacent vertices. Adjacent vertices of
0 are 1 and 7. The distance values of 1 and 7 are updated as 4 and 8. Following subgraph
shows vertices and their distance values, only the vertices with finite distance values are
shown. The vertices included in SPT are shown in green colour.
Pick the vertex with minimum distance value and not already included in SPT (not in
sptSET). The vertex 1 is picked and added to sptSet. So sptSet now becomes {0, 1}.
Update the distance values of adjacent vertices of 1. The distance value of vertex 2 becomes
12.
Pick the vertex with minimum distance value and not already included in SPT (not in
sptSET). Vertex 7 is picked. So sptSet now becomes {0, 1, 7}. Update the distance values
of adjacent vertices of 7. The distance value of vertex 6 and 8 becomes finite (15 and 9
respectively).
981
Chapter 135. Dijkstra’s shortest path algorithm Greedy Algo-7
Pick the vertex with minimum distance value and not already included in SPT (not in
sptSET). Vertex 6 is picked. So sptSet now becomes {0, 1, 7, 6}. Update the distance
values of adjacent vertices of 6. The distance value of vertex 5 and 8 are updated.
We repeat the above steps until sptSet doesn’t include all vertices of given graph. Finally,
we get the following Shortest Path Tree (SPT).
982
Chapter 135. Dijkstra’s shortest path algorithm Greedy Algo-7
#define V 9
// A utility function to find the vertex with minimum distance value, from
// the set of vertices not yet included in shortest path tree
int minDistance(int dist[], bool sptSet[])
{
// Initialize min value
int min = INT_MAX, min_index;
for (int v = 0; v < V; v++)
if (sptSet[v] == false && dist[v] <= min)
min = dist[v], min_index = v;
return min_index;
}
// A utility function to print the constructed distance array
int printSolution(int dist[], int n)
{
printf("Vertex Distance from Source\n");
for (int i = 0; i < V; i++)
printf("%d tt %d\n", i, dist[i]);
}
// Function that implements Dijkstra's single source shortest path algorithm
// for a graph represented using adjacency matrix representation
void dijkstra(int graph[V][V], int src)
{
int dist[V]; // The output array. dist[i] will hold the shortest
// distance from src to i
bool sptSet[V]; // sptSet[i] will true if vertex i is included in shortest
// path tree or shortest distance from src to i is finalized
// Initialize all distances as INFINITE and stpSet[] as false
for (int i = 0; i < V; i++)
dist[i] = INT_MAX, sptSet[i] = false;
// Distance of source vertex from itself is always 0
dist[src] = 0;
// Find shortest path for all vertices
for (int count = 0; count < V-1; count++)
{
// Pick the minimum distance vertex from the set of vertices not
// yet processed. u is always equal to src in the first iteration.
int u = minDistance(dist, sptSet);
983
Chapter 135. Dijkstra’s shortest path algorithm Greedy Algo-7
Java
984
Chapter 135. Dijkstra’s shortest path algorithm Greedy Algo-7
// A utility function to find the vertex with minimum distance value,
// from the set of vertices not yet included in shortest path tree
static final int V=9;
int minDistance(int dist[], Boolean sptSet[])
{
// Initialize min value
int min = Integer.MAX_VALUE, min_index=-1;
for (int v = 0; v < V; v++)
if (sptSet[v] == false && dist[v] <= min)
{
min = dist[v];
min_index = v;
}
return min_index;
}
// A utility function to print the constructed distance array
void printSolution(int dist[], int n)
{
System.out.println("Vertex Distance from Source");
for (int i = 0; i < V; i++)
System.out.println(i+" tt "+dist[i]);
}
// Funtion that implements Dijkstra's single source shortest path
// algorithm for a graph represented using adjacency matrix
// representation
void dijkstra(int graph[][], int src)
{
int dist[] = new int[V]; // The output array. dist[i] will hold
// the shortest distance from src to i
// sptSet[i] will true if vertex i is included in shortest
// path tree or shortest distance from src to i is finalized
Boolean sptSet[] = new Boolean[V];
// Initialize all distances as INFINITE and stpSet[] as false
for (int i = 0; i < V; i++)
{
dist[i] = Integer.MAX_VALUE;
sptSet[i] = false;
}
// Distance of source vertex from itself is always 0
dist[src] = 0;
985
Chapter 135. Dijkstra’s shortest path algorithm Greedy Algo-7
986
Chapter 135. Dijkstra’s shortest path algorithm Greedy Algo-7
Python
987
Chapter 135. Dijkstra’s shortest path algorithm Greedy Algo-7
# Pick the minimum distance vertex from
# the set of vertices not yet processed.
# u is always equal to src in first iteration
u = self.minDistance(dist, sptSet)
# Put the minimum distance vertex in the
# shotest path tree
sptSet[u] = True
# Update dist value of the adjacent vertices
# of the picked vertex only if the current
# distance is greater than new distance and
# the vertex in not in the shotest path tree
for v in range(self.V):
if self.graph[u][v] > 0 and sptSet[v] == False and
dist[v] > dist[u] + self.graph[u][v]:
dist[v] = dist[u] + self.graph[u][v]
self.printSolution(dist)
# Driver program
g = Graph(9)
g.graph = [[0, 4, 0, 0, 0, 0, 0, 8, 0],
[4, 0, 8, 0, 0, 0, 0, 11, 0],
[0, 8, 0, 7, 0, 4, 0, 0, 2],
[0, 0, 7, 0, 9, 14, 0, 0, 0],
[0, 0, 0, 9, 0, 10, 0, 0, 0],
[0, 0, 4, 14, 10, 0, 2, 0, 0],
[0, 0, 0, 0, 0, 2, 0, 1, 6],
[8, 11, 0, 0, 0, 0, 1, 0, 7],
[0, 0, 2, 0, 0, 0, 6, 7, 0]
];
g.dijkstra(0);
# This code is contributed by Divyanshu Mehta
Output:
988
Chapter 135. Dijkstra’s shortest path algorithm Greedy Algo-7
7 8
8 14
Notes:
1) The code calculates shortest distance, but doesn’t calculate the path information. We
can create a parent array, update the parent array when distance is updated (like prim’s
implementation) and use it show the shortest path from source to different vertices.
2) The code is for undirected graph, same dijkstra function can be used for directed graphs
also.
3) The code finds shortest distances from source to all vertices. If we are interested only in
shortest distance from the source to a single target, we can break the for the loop when the
picked minimum distance vertex is equal to target (Step 3.a of the algorithm).
4) Time Complexity of the implementation is O(V^2). If the input graph is represented
using adjacency list, it can be reduced to O(E log V) with the help of binary heap. Please
see
Dijkstra’s Algorithm for Adjacency List Representation for more details.
5) Dijkstra’s algorithm doesn’t work for graphs with negative weight edges. For graphs with
negative weight edges, Bellman–Ford algorithm can be used, we will soon be discussing it
as a separate post.
Dijkstra’s Algorithm for Adjacency List Representation
Printing Paths in Dijkstra’s Shortest Path Algorithm
Dijkstra’s shortest path algorithm using set in STL
Source
https://www.geeksforgeeks.org/dijkstras-shortest-path-algorithm-greedy-algo-7/
989
Chapter 136
Problem Statement :
Given a graph which represents a flow network where every edge has a capacity. Also given
two vertices source ‘s’ and sink ‘t’ in the graph, find the maximum possible flow from s to t
with following constraints :
990
Chapter 136. Dinic’s algorithm for Maximum Flow
Background :
Time complexity of Edmond Karp Implementation is O(VE2 ). In this post, a new Dinic’s
algorithm is discussed which is a faster algorithm and takes O(EV2 ).
Like Edmond Karp’s algorithm, Dinic’s algorithm uses following concepts :
In Edmond’s Karp algorithm, we use BFS to find an augmenting path and send flow across
this path. In Dinic’s algorithm, we use BFS to check if more flow is possible and to construct
level graph. In level graph, we assign levels to all nodes, level of a node is shortest distance
(in terms of number of edges) of the node from source. Once level graph is constructed, we
send multiple flows using this level graph. This is the reason it works better than Edmond
Karp. In Edmond Karp, we send only flow that is send across the path found by BFS.
Outline of Dinic’s algorithm :
991
Chapter 136. Dinic’s algorithm for Maximum Flow
A flow is Blocking Flow if no more flow can be sent using level graph, i.e., no more s-t
path exists such that path vertices have current levels 0, 1, 2… in order. Blocking Flow can
be seen same as maximum flow path in Greedy algorithm discussed discussed here.
Illustration :
Initial Residual Graph (Same as given Graph)
Total Flow = 0
First Iteration : We assign levels to all nodes using BFS. We also check if more flow is
possible (or there is a s-t path in residual graph).
992
Chapter 136. Dinic’s algorithm for Maximum Flow
Now we find blocking flow using levels (means every flow path should have levels as 0, 1, 2,
3). We send three flows together. This is where it is optimized compared to Edmond Karp
where we send one flow at a time.
4 units of flow on path s – 1 – 3 – t.
6 units of flow on path s – 1 – 4 – t.
4 units of flow on path s – 2 – 4 – t.
Total flow = Total flow + 4 + 6 + 4 = 14
After one iteration, residual graph changes to following.
Second Iteration : We assign new levels to all nodes using BFS of above modified residual
graph. We also check if more flow is possible (or there is a s-t path in residual graph).
993
Chapter 136. Dinic’s algorithm for Maximum Flow
Now we find blocking flow using levels (means every flow path should have levels as 0, 1, 2,
3, 4). We can send only one flow this time.
5 units of flow on path s – 2 – 4 – 3 – t
Total flow = Total flow + 5 = 19
The new residual graph is
Third Iteration : We run BFS and create a level graph. We also check if more flow is
possible and proceed only if possible. This time there is no s-t path in residual graph, so
we terminate the algorithm.
Implementation :
Below is c++ implementation of Dinic’s algorithm:
994
Chapter 136. Dinic’s algorithm for Maximum Flow
// Residual Graph
class Graph
{
int V; // number of vertex
int *level ; // stores level of a node
vector< Edge > *adj;
public :
Graph(int V)
{
adj = new vector<Edge>[V];
this->V = V;
level = new int[V];
}
// add edge to the graph
void addEdge(int u, int v, int C)
{
// Forward edge : 0 flow and C capacity
Edge a{v, 0, C, adj[v].size()};
// Back edge : 0 flow and 0 capacity
Edge b{u, 0, 0, adj[u].size()};
adj[u].push_back(a);
adj[v].push_back(b); // reverse edge
}
bool BFS(int s, int t);
int sendFlow(int s, int flow, int t, int ptr[]);
int DinicMaxflow(int s, int t);
};
// Finds if more flow can be sent from s to t.
// Also assigns levels to nodes.
bool Graph::BFS(int s, int t)
{
for (int i = 0 ; i < V ; i++)
level[i] = -1;
level[s] = 0; // Level of source vertex
// Create a queue, enqueue source vertex
// and mark source vertex as visited here
// level[] array works as visited array also.
list< int > q;
q.push_back(s);
995
Chapter 136. Dinic’s algorithm for Maximum Flow
vector<Edge>::iterator i ;
while (!q.empty())
{
int u = q.front();
q.pop_front();
for (i = adj[u].begin(); i != adj[u].end(); i++)
{
Edge &e = *i;
if (level[e.v] < 0 && e.flow < e.C)
{
// Level of current vertex is,
// level of parent + 1
level[e.v] = level[u] + 1;
q.push_back(e.v);
}
}
}
// IF we can not reach to the sink we
// return false else true
return level[t] < 0 ? false : true ;
}
// A DFS based function to send flow after BFS has
// figured out that there is a possible flow and
// constructed levels. This function called multiple
// times for a single call of BFS.
// flow : Current flow send by parent function call
// start[] : To keep track of next edge to be explored.
// start[i] stores count of edges explored
// from i.
// u : Current vertex
// t : Sink
int Graph::sendFlow(int u, int flow, int t, int start[])
{
// Sink reached
if (u == t)
return flow;
// Traverse all adjacent edges one -by - one.
for ( ; start[u] < adj[u].size(); start[u]++)
{
// Pick next edge from adjacency list of u
Edge &e = adj[u][start[u]];
if (level[e.v] == level[u]+1 && e.flow < e.C)
{
996
Chapter 136. Dinic’s algorithm for Maximum Flow
997
Chapter 136. Dinic’s algorithm for Maximum Flow
}
// Driver program to test above functions
int main()
{
Graph g(6);
g.addEdge(0, 1, 16 );
g.addEdge(0, 2, 13 );
g.addEdge(1, 2, 10 );
g.addEdge(1, 3, 12 );
g.addEdge(2, 1, 4 );
g.addEdge(2, 4, 14);
g.addEdge(3, 2, 9 );
g.addEdge(3, 5, 20 );
g.addEdge(4, 3, 7 );
g.addEdge(4, 5, 4);
// next exmp
/*g.addEdge(0, 1, 3 );
g.addEdge(0, 2, 7 ) ;
g.addEdge(1, 3, 9);
g.addEdge(1, 4, 9 );
g.addEdge(2, 1, 9 );
g.addEdge(2, 4, 9);
g.addEdge(2, 5, 4);
g.addEdge(3, 5, 3);
g.addEdge(4, 5, 7 );
g.addEdge(0, 4, 10);
// next exp
g.addEdge(0, 1, 10);
g.addEdge(0, 2, 10);
g.addEdge(1, 3, 4 );
g.addEdge(1, 4, 8 );
g.addEdge(1, 2, 2 );
g.addEdge(2, 4, 9 );
g.addEdge(3, 5, 10 );
g.addEdge(4, 3, 6 );
g.addEdge(4, 5, 10 ); */
cout << "Maximum flow " << g.DinicMaxflow(0, 5);
return 0;
}
Output:
Maximum flow 23
998
Chapter 136. Dinic’s algorithm for Maximum Flow
Time Complexity : O(EV2 ). Doing a BFS to construct level graph takes O(E) time.
Sending multiple more flows until a blocking flow is reached takes O(VE) time. The outer
loop runs at-most O(V) time. In each iteration, we construct new level graph and find
blocking flow. It can be proved that the number of levels increase at least by one in every
iteration (Refer the below reference video for the proof). So the outer loop runs at most
O(V) times. Therefore overall time complexity is O(EV2 ).
References :
https://en.wikipedia.org/wiki/Dinic’s_algorithm
https://www.youtube.com/watch?v=uM06jHdIC70
Source
https://www.geeksforgeeks.org/dinics-algorithm-maximum-flow/
999
Chapter 137
Disjoint Set (Or Union-Find) Set 1 (Detect Cycle in an Undirected Graph) - GeeksforGeeks
A disjoint-set data structure is a data structure that keeps track of a set of elements par-
titioned into a number of disjoint (non-overlapping) subsets. A union-find algorithm is an
algorithm that performs two useful operations on such a data structure:
Find: Determine which subset a particular element is in. This can be used for determining
if two elements are in the same subset.
Union: Join two subsets into a single subset.
In this post, we will discuss an application of Disjoint Set Data Structure. The application
is to check whether a given graph contains a cycle or not.
Union-Find Algorithm can be used to check whether an undirected graph contains cycle or
not. Note that we have discussed an algorithm to detect cycle. This is another method
based on Union-Find. This method assumes that graph doesn’t contain any self-loops.
We can keeps track of the subsets in a 1D array, lets call it parent[].
Let us consider the following graph:
1000
Chapter 137. Disjoint Set (Or Union-Find) Set 1 (Detect Cycle in an Undirected Graph)
For each edge, make subsets using both the vertices of the edge. If both the vertices are in
the same subset, a cycle is found.
Initially, all slots of parent array are initialized to -1 (means there is only one item in every
subset).
0 1 2
-1 -1 -1
Edge 0-2: 0 is in subset 2 and 2 is also in subset 2. Hence, including this edge forms a cycle.
How subset of 0 is same as 2?
0->1->2 // 1 is parent of 0 and 2 is parent of 1
Based on the above explanation, below are implementations:
C/C++
1001
Chapter 137. Disjoint Set (Or Union-Find) Set 1 (Detect Cycle in an Undirected Graph)
1002
Chapter 137. Disjoint Set (Or Union-Find) Set 1 (Detect Cycle in an Undirected Graph)
if(xset!=yset){
parent[xset] = yset;
}
}
// The main function to check whether a given graph contains
// cycle or not
int isCycle( struct Graph* graph )
{
// Allocate memory for creating V subsets
int *parent = (int*) malloc( graph->V * sizeof(int) );
// Initialize all subsets as single element sets
memset(parent, -1, sizeof(int) * graph->V);
// Iterate through all edges of graph, find subset of both
// vertices of every edge, if both subsets are same, then
// there is cycle in graph.
for(int i = 0; i < graph->E; ++i)
{
int x = find(parent, graph->edge[i].src);
int y = find(parent, graph->edge[i].dest);
if (x == y)
return 1;
Union(parent, x, y);
}
return 0;
}
// Driver program to test above functions
int main()
{
/* Let us create following graph
0
| \
| \
1-----2 */
int V = 3, E = 3;
struct Graph* graph = createGraph(V, E);
// add edge 0-1
graph->edge[0].src = 0;
graph->edge[0].dest = 1;
// add edge 1-2
graph->edge[1].src = 1;
1003
Chapter 137. Disjoint Set (Or Union-Find) Set 1 (Detect Cycle in an Undirected Graph)
graph->edge[1].dest = 2;
// add edge 0-2
graph->edge[2].src = 0;
graph->edge[2].dest = 2;
if (isCycle(graph))
printf( "graph contains cycle" );
else
printf( "graph doesn't contain cycle" );
return 0;
}
Java
1004
Chapter 137. Disjoint Set (Or Union-Find) Set 1 (Detect Cycle in an Undirected Graph)
// A utility function to do union of two subsets
void Union(int parent[], int x, int y)
{
int xset = find(parent, x);
int yset = find(parent, y);
parent[xset] = yset;
}
// The main function to check whether a given graph
// contains cycle or not
int isCycle( Graph graph)
{
// Allocate memory for creating V subsets
int parent[] = new int[graph.V];
// Initialize all subsets as single element sets
for (int i=0; i<graph.V; ++i)
parent[i]=-1;
// Iterate through all edges of graph, find subset of both
// vertices of every edge, if both subsets are same, then
// there is cycle in graph.
for (int i = 0; i < graph.E; ++i)
{
int x = graph.find(parent, graph.edge[i].src);
int y = graph.find(parent, graph.edge[i].dest);
if (x == y)
return 1;
graph.Union(parent, x, y);
}
return 0;
}
// Driver Method
public static void main (String[] args)
{
/* Let us create following graph
0
| \
| \
1-----2 */
int V = 3, E = 3;
Graph graph = new Graph(V, E);
1005
Chapter 137. Disjoint Set (Or Union-Find) Set 1 (Detect Cycle in an Undirected Graph)
Python
1006
Chapter 137. Disjoint Set (Or Union-Find) Set 1 (Detect Cycle in an Undirected Graph)
y_set = self.find_parent(parent, y)
parent[x_set] = y_set
# The main function to check whether a given graph
# contains cycle or not
def isCyclic(self):
# Allocate memory for creating V subsets and
# Initialize all subsets as single element sets
parent = [-1]*(self.V)
# Iterate through all edges of graph, find subset of both
# vertices of every edge, if both subsets are same, then
# there is cycle in graph.
for i in self.graph:
for j in self.graph[i]:
x = self.find_parent(parent, i)
y = self.find_parent(parent, j)
if x == y:
return True
self.union(parent,x,y)
# Create a graph given in the above diagram
g = Graph(3)
g.addEdge(0, 1)
g.addEdge(1, 2)
g.addEdge(2, 0)
if g.isCyclic():
print "Graph contains cycle"
else :
print "Graph does not contain cycle "
#This code is contributed by Neelam Yadav
Output:
Note that the implementation of union() and find() is naive and takes O(n) time in worst
case. These methods can be improved to O(Logn) using Union by Rank or Height. We will
soon be discussing Union by Rank in a separate post.
Related Articles :
Union-Find Algorithm Set 2 (Union By Rank and Path Compression)
1007
Chapter 137. Disjoint Set (Or Union-Find) Set 1 (Detect Cycle in an Undirected Graph)
Source
https://www.geeksforgeeks.org/union-find/
1008
Chapter 138
Input : N = 3, M = 4
mat[][] = {
0, 0, 0, 1,
0, 0, 1, 1,
0, 1, 1, 0
}
Output : 3 2 1 0
2 1 0 0
1 0 0 1
1009
Chapter 138. Distance of nearest cell having 1 in a binary matrix
1010
Chapter 138. Distance of nearest cell having 1 in a binary matrix
int mat[N][M] =
{
0, 0, 0, 1,
0, 0, 1, 1,
0, 1, 1, 0
};
printDistance(mat);
return 0;
}
Java
1011
Chapter 138. Distance of nearest cell having 1 in a binary matrix
Math.min(ans[i][j],
Math.abs(i-k)
+ Math.abs(j-l));
}
}
// Printing the answer.
for (int i = 0; i < N; i++)
{
for (int j = 0; j < M; j++)
System.out.print( ans[i][j] + " ");
System.out.println();
}
}
// Driven Program
public static void main (String[] args)
{
int mat[][] = { {0, 0, 0, 1},
{0, 0, 1, 1},
{0, 1, 1, 0} };
printDistance(mat);
}
}
// This code is contributed by anuj_67.
C#
1012
Chapter 138. Distance of nearest cell having 1 in a binary matrix
PHP
1013
Chapter 138. Distance of nearest cell having 1 in a binary matrix
<?php
// PHP program to find distance of nearest
// cell having 1 in a binary matrix.
$N = 3;
$M = 4;
// Print the distance of nearest cell
// having 1 for each cell.
function printDistance( $mat)
{
global $N,$M;
$ans = array(array());
// Initalize the answer
// matrix with INT_MAX.
for($i = 0; $i < $N; $i++)
for ( $j = 0; $j < $M; $j++)
$ans[$i][$j] = PHP_INT_MAX;
// For each cell
for ( $i = 0; $i < $N; $i++)
for ( $j = 0; $j < $M; $j++)
{
// Traversing the whole matrix
// to find the minimum distance.
for ($k = 0; $k < $N; $k++)
for ( $l = 0; $l < $M; $l++)
{
// If cell contain 1, check
// for minimum distance.
if ($mat[$k][$l] == 1)
$ans[$i][$j] = min($ans[$i][$j],
abs($i-$k) + abs($j - $l));
}
}
// Printing the answer.
for ( $i = 0; $i < $N; $i++)
{
for ( $j = 0; $j < $M; $j++)
echo $ans[$i][$j] , " ";
echo "\n";
}
}
1014
Chapter 138. Distance of nearest cell having 1 in a binary matrix
Output:
3 2 1 0
2 1 0 0
1 0 0 1
1. Create a graph with values assigned from 1 to M*N to all vertices. The purpose is to
store position and adjacent information.
2. Create an empty queue.
1015
Chapter 138. Distance of nearest cell having 1 in a binary matrix
1016
Chapter 138. Distance of nearest cell having 1 in a binary matrix
g[k].push_back(k+m);
g[k+m].push_back(k);
}
k++;
}
}
}
// BFS function to find minimum distance
void bfs(bool visit[], int dist[], queue<int> q)
{
while (!q.empty())
{
int temp = q.front();
q.pop();
for (int i = 0; i < g[temp].size(); i++)
{
if (visit[g[temp][i]] != 1)
{
dist[g[temp][i]] =
min(dist[g[temp][i]], dist[temp]+1);
q.push(g[temp][i]);
visit[g[temp][i]] = 1;
}
}
}
}
// Printing the solution.
void print(int dist[])
{
for (int i = 1, c = 1; i <= n*m; i++, c++)
{
cout << dist[i] << " ";
if (c%m == 0)
cout << endl;
}
}
};
// Find minimum distance
void findMinDistance(bool mat[N][M])
{
// Creating a graph with nodes values assigned
1017
Chapter 138. Distance of nearest cell having 1 in a binary matrix
1018
Chapter 138. Distance of nearest cell having 1 in a binary matrix
0, 0, 1, 1,
0, 1, 1, 0
};
findMinDistance(mat);
return 0;
}
Output :
3 2 1 0
2 1 0 0
1 0 0 1
Source
https://www.geeksforgeeks.org/distance-nearest-cell-1-binary-matrix/
1019
Chapter 139
1020
Chapter 139. Dominant Set of a Graph
Examples:
It is believed that there may be no efficient algorithm that finds a smallest dominating set
for all graphs, but there are efficient approximation algorithms.
Algorithm :
1021
Chapter 139. Dominant Set of a Graph
1022
Chapter 139. Dominant Set of a Graph
g[2].push_back(3);
g[3].push_back(2); // x = 3, y = 4 ;
g[0].push_back(3);
g[3].push_back(0); // x = 1, y = 4 ;
g[3].push_back(4);
g[4].push_back(3); // x = 4, y = 5 ;
g[2].push_back(4);
g[4].push_back(2); // x = 3, y = 5 ;
vector<int> S = Dominant(ver, edge);
cout << "The Dominant Set is : { ";
for (int i = 0; i < (int)S.size(); i++)
cout << S[i] + 1 << " ";
cout << "}";
return 0;
}
Output:
Reference : wiki
Source
https://www.geeksforgeeks.org/dominant-set-of-a-graph/
1023
Chapter 140
In this article only Incremental connectivity is discussed. There are mainly two opera-
tions that need to be handled.
2. Information about two nodes x and y whether they are in the same connected compo-
nents or not.
Example:
Input : V = 7
Number of operations = 11
1 0 1
2 0 1
2 1 2
1024
Chapter 140. Dynamic Connectivity Set 1 (Incremental)
1 0 2
2 0 2
2 2 3
2 3 4
1 0 5
2 4 5
2 5 6
1 2 6
Note: 7 represents number of nodes,
11 represents number of queries.
There are two types of queries
Type 1 : 1 x y in this if the node
x and y are connected print
Yes else No
Type 2 : 2 x y in this add an edge
between node x and y
Output : No
Yes
No
Yes
Explanation :
Initially there are no edges so node 0 and 1
will be disconnected so answer will be No
Node 0 and 2 will be connected through node
1 so answer will be Yes similarly for other
queries we can find whether two nodes are
connected or not
To solve the problems of incremental connectivity disjoint data structure is used. Here each
connected component represents a set and if the two nodes belong to the same set it means
that they are connected.
C++ implementation is given below here we are using union by rank and path compression
1025
Chapter 140. Dynamic Connectivity Set 1 (Incremental)
// union of two nodes a and b
void weighted_union(int arr[], int rank[],
int a, int b)
{
int root_a = root (arr, a);
int root_b = root (arr, b);
// union based on rank
if (rank[root_a] < rank[root_b])
{
arr[root_a] = arr[root_b];
rank[root_b] += rank[root_a];
}
else
{
arr[root_b] = arr[root_a];
rank[root_a] += rank[root_b];
}
}
// Returns true if two nodes have same root
bool areSame(int arr[], int a, int b)
{
return (root(arr, a) == root(arr, b));
}
// Performing an operation according to query type
void query(int type, int x, int y, int arr[], int rank[])
{
// type 1 query means checking if node x and y
// are connected or not
if (type == 1)
{
// If roots of x and y is same then yes
// is the answer
if (areSame(arr, x, y) == true)
cout << "Yes" << endl;
else
cout << "No" << endl;
}
// type 2 query refers union of x and y
else if (type == 2)
{
// If x and y have different roots then
// union them
if (areSame(arr, x, y) == false)
1026
Chapter 140. Dynamic Connectivity Set 1 (Incremental)
Output:
No
Yes
No
Yes
1027
Chapter 140. Dynamic Connectivity Set 1 (Incremental)
Time Complexity:
The amortized time complexity is O(alpha(n)) per operation where alpha is inverse acker-
mann function which is nearly constant.
Reference:
https://en.wikipedia.org/wiki/Dynamic_connectivity
Source
https://www.geeksforgeeks.org/dynamic-connectivity-set-1-incremental/
1028
Chapter 141
1029
Chapter 141. Erdos Renyl Model (for generating Random Graphs)
0.5 corresponds to the case where all graphs on n vertices are chosen with equal
probability.
The article will basically deal with the G (n,p) model where n is the no of nodes to be
created and p defines the probability of joining of each node to the other.
Properties of G(n, p)
With the notation above, a graph in G(n, p) has on average edges. The distribution
of the degree of any particular vertex is binomial:
as and np=
constant
This distribution is Poisson for large n and np = const.
In a 1960 paper, Erdos and Rényi described the behaviour of G(n, p) very precisely for
various values of p. Their results included that:
If np < 1, then a graph in G(n, p) will almost surely have no connected components of size
larger than O(log(n)).
If np = 1, then a graph in G(n, p) will almost surely have a largest component whose size
is of order .
If np c > 1, where c is a constant, then a graph in G(n, p) will almost surely have a
unique giant component containing a positive fraction of the vertices. No other component
will contain more than O(log(n)) vertices.
1030
Chapter 141. Erdos Renyl Model (for generating Random Graphs)
Next I’ll describe the code to be used for making the ER graph. For implementation of
the code below, you’ll need to install the netwrokx library as well you’ll need to install the
matplotlib library. Following you’ll see the exact code of the graph which has been used as
a function of the networkx library lately in this article.
Erdos_renyi_graph(n, p, seed=None, directed=False)
Returns a G(n,p) random graph, also known as an Erd?s-Rényi graph or a binomial graph.
The G(n,p) model chooses each of the possible edges with probability p.
The functions binomial_graph() and erdos_renyi_graph() are aliases of this function.
Parameters: n (int) – The number of nodes.
p (float) – Probability for edge creation.
seed (int, optional) – Seed for random number generator (default=None).
directed (bool, optional (default=False)) – If True, this function returns a directed graph.
>>> I= nx.erdos_renyi_graph(10,0)
>>> nx.draw(I, with_labels=True)
>>> plt.show()
1031
Chapter 141. Erdos Renyl Model (for generating Random Graphs)
>>> K=nx.erdos_renyi_graph(10,0.25)
>>> nx.draw(K, with_labels=True)
>>> plt.show()
>>>H= nx.erdos_renyi_graph(10,0.5)
>>> nx.draw(H, with_labels=True)
>>> plt.show()
1032
Chapter 141. Erdos Renyl Model (for generating Random Graphs)
This algorithm runs in O( ) time. For sparse graphs (that is, for small values of p),
fast_gnp_random_graph() is a faster algorithm.
Thus the above examples clearly define the use of erdos renyi model to make random graphs
and how to use the foresaid using the networkx library of python.
Next we will discuss the ego graph and various other types of graphs in python using the
library networkx.
References
You can read more about the same at
https://en.wikipedia.org/wiki/Erd%C5%91s%E2%80%93R%C3%A9nyi_model
http://networkx.readthedocs.io/en/networkx-1.10/index.html
.
Source
https://www.geeksforgeeks.org/erdos-renyl-model-generating-random-graphs/
1033
Chapter 142
1034
Chapter 142. Eulerian path and circuit for undirected graph
1035
Chapter 142. Eulerian path and circuit for undirected graph
class Graph
{
int V; // No. of vertices
list<int> *adj; // A dynamic array of adjacency lists
public:
// Constructor and destructor
Graph(int V) {this->V = V; adj = new list<int>[V]; }
~Graph() { delete [] adj; } // To avoid memory leak
// function to add an edge to graph
void addEdge(int v, int w);
// Method to check if this graph is Eulerian or not
int isEulerian();
// Method to check if all non-zero degree vertices are connected
bool isConnected();
// Function to do DFS starting from v. Used in isConnected();
void DFSUtil(int v, bool visited[]);
};
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w);
adj[w].push_back(v); // Note: the graph is undirected
}
void Graph::DFSUtil(int v, bool visited[])
{
// Mark the current node as visited and print it
visited[v] = true;
// Recur for all the vertices adjacent to this vertex
list<int>::iterator i;
for (i = adj[v].begin(); i != adj[v].end(); ++i)
if (!visited[*i])
DFSUtil(*i, visited);
}
// Method to check if all non-zero degree vertices are connected.
// It mainly does DFS traversal starting from
bool Graph::isConnected()
{
// Mark all the vertices as not visited
bool visited[V];
int i;
for (i = 0; i < V; i++)
1036
Chapter 142. Eulerian path and circuit for undirected graph
visited[i] = false;
// Find a vertex with non-zero degree
for (i = 0; i < V; i++)
if (adj[i].size() != 0)
break;
// If there are no edges in the graph, return true
if (i == V)
return true;
// Start DFS traversal from a vertex with non-zero degree
DFSUtil(i, visited);
// Check if all non-zero degree vertices are visited
for (i = 0; i < V; i++)
if (visited[i] == false && adj[i].size() > 0)
return false;
return true;
}
/* The function returns one of the following values
0 --> If grpah is not Eulerian
1 --> If graph has an Euler path (Semi-Eulerian)
2 --> If graph has an Euler Circuit (Eulerian) */
int Graph::isEulerian()
{
// Check if all non-zero degree vertices are connected
if (isConnected() == false)
return 0;
// Count vertices with odd degree
int odd = 0;
for (int i = 0; i < V; i++)
if (adj[i].size() & 1)
odd++;
// If count is more than 2, then graph is not Eulerian
if (odd > 2)
return 0;
// If odd count is 2, then semi-eulerian.
// If odd count is 0, then eulerian
// Note that odd count can never be 1 for undirected graph
return (odd)? 1 : 2;
}
1037
Chapter 142. Eulerian path and circuit for undirected graph
1038
Chapter 142. Eulerian path and circuit for undirected graph
test(g4);
// Let us create a graph with all veritces
// with zero degree
Graph g5(3);
test(g5);
return 0;
}
Java
1039
Chapter 142. Eulerian path and circuit for undirected graph
1040
Chapter 142. Eulerian path and circuit for undirected graph
return 0;
// Count vertices with odd degree
int odd = 0;
for (int i = 0; i < V; i++)
if (adj[i].size()%2!=0)
odd++;
// If count is more than 2, then graph is not Eulerian
if (odd > 2)
return 0;
// If odd count is 2, then semi-eulerian.
// If odd count is 0, then eulerian
// Note that odd count can never be 1 for undirected graph
return (odd==2)? 1 : 2;
}
// Function to run test cases
void test()
{
int res = isEulerian();
if (res == 0)
System.out.println("graph is not Eulerian");
else if (res == 1)
System.out.println("graph has a Euler path");
else
System.out.println("graph has a Euler cycle");
}
// Driver method
public static void main(String args[])
{
// Let us create and test graphs shown in above figures
Graph g1 = new Graph(5);
g1.addEdge(1, 0);
g1.addEdge(0, 2);
g1.addEdge(2, 1);
g1.addEdge(0, 3);
g1.addEdge(3, 4);
g1.test();
Graph g2 = new Graph(5);
g2.addEdge(1, 0);
g2.addEdge(0, 2);
g2.addEdge(2, 1);
g2.addEdge(0, 3);
g2.addEdge(3, 4);
1041
Chapter 142. Eulerian path and circuit for undirected graph
g2.addEdge(4, 0);
g2.test();
Graph g3 = new Graph(5);
g3.addEdge(1, 0);
g3.addEdge(0, 2);
g3.addEdge(2, 1);
g3.addEdge(0, 3);
g3.addEdge(3, 4);
g3.addEdge(1, 3);
g3.test();
// Let us create a graph with 3 vertices
// connected in the form of cycle
Graph g4 = new Graph(3);
g4.addEdge(0, 1);
g4.addEdge(1, 2);
g4.addEdge(2, 0);
g4.test();
// Let us create a graph with all veritces
// with zero degree
Graph g5 = new Graph(3);
g5.test();
}
}
// This code is contributed by Aakash Hasija
Python
1042
Chapter 142. Eulerian path and circuit for undirected graph
def DFSUtil(self,v,visited):
# Mark the current node as visited
visited[v]= True
#Recur for all the vertices adjacent to this vertex
for i in self.graph[v]:
if visited[i]==False:
self.DFSUtil(i,visited)
'''Method to check if all non-zero degree vertices are
connected. It mainly does DFS traversal starting from
node with non-zero degree'''
def isConnected(self):
# Mark all the vertices as not visited
visited =[False]*(self.V)
# Find a vertex with non-zero degree
for i in range(self.V):
if len(self.graph[i]) > 1:
break
# If there are no edges in the graph, return true
if i == self.V-1:
return True
# Start DFS traversal from a vertex with non-zero degree
self.DFSUtil(i,visited)
# Check if all non-zero degree vertices are visited
for i in range(self.V):
if visited[i]==False and len(self.graph[i]) > 0:
return False
return True
'''The function returns one of the following values
0 --> If grpah is not Eulerian
1 --> If graph has an Euler path (Semi-Eulerian)
2 --> If graph has an Euler Circuit (Eulerian) '''
def isEulerian(self):
# Check if all non-zero degree vertices are connected
if self.isConnected() == False:
return 0
else:
#Count vertices with odd degree
1043
Chapter 142. Eulerian path and circuit for undirected graph
odd = 0
for i in range(self.V):
if len(self.graph[i]) % 2 !=0:
odd +=1
'''If odd count is 2, then semi-eulerian.
If odd count is 0, then eulerian
If count is more than 2, then graph is not Eulerian
Note that odd count can never be 1 for undirected graph'''
if odd == 0:
return 2
elif odd == 2:
return 1
elif odd > 2:
return 0
# Function to run test cases
def test(self):
res = self.isEulerian()
if res == 0:
print "graph is not Eulerian"
elif res ==1 :
print "graph has a Euler path"
else:
print "graph has a Euler cycle"
#Let us create and test graphs shown in above figures
g1 = Graph(5);
g1.addEdge(1, 0)
g1.addEdge(0, 2)
g1.addEdge(2, 1)
g1.addEdge(0, 3)
g1.addEdge(3, 4)
g1.test()
g2 = Graph(5)
g2.addEdge(1, 0)
g2.addEdge(0, 2)
g2.addEdge(2, 1)
g2.addEdge(0, 3)
g2.addEdge(3, 4)
g2.addEdge(4, 0)
g2.test();
g3 = Graph(5)
1044
Chapter 142. Eulerian path and circuit for undirected graph
g3.addEdge(1, 0)
g3.addEdge(0, 2)
g3.addEdge(2, 1)
g3.addEdge(0, 3)
g3.addEdge(3, 4)
g3.addEdge(1, 3)
g3.test()
#Let us create a graph with 3 vertices
# connected in the form of cycle
g4 = Graph(3)
g4.addEdge(0, 1)
g4.addEdge(1, 2)
g4.addEdge(2, 0)
g4.test()
# Let us create a graph with all veritces
# with zero degree
g5 = Graph(3)
g5.test()
#This code is contributed by Neelam Yadav
Output:
Source
https://www.geeksforgeeks.org/eulerian-path-and-circuit/
1045
Chapter 143
The base case of this problem is if number of vertices with odd number of edges(i.e. odd
degree) is greater than 2 then there is no Eulerian path.
If it has solution and all the nodes has even number of edges then we can start our path
from any of the nodes.
If it has solution and exactly two vertices has odd number of edges then we has to start our
path from one of these two vertices.
1046
Chapter 143. Eulerian Path in undirected graph
There will not be the case where exactly one vertex has odd number of edges, as there is
even number of edges in total.
Process to Find the Path:
5. Repeat process 3 and 4 until the stack is empty and current node has not any neigh-
bour.
1047
Chapter 143. Eulerian Path in undirected graph
1048
Chapter 143. Eulerian Path in undirected graph
1049
Chapter 143. Eulerian Path in undirected graph
Output:
1050
Chapter 143. Eulerian Path in undirected graph
Time Complexity:
The runtime complexity of this algorithm is O(E). This algorithm can also be used to find
the Eulerian circuit. If the first and last vertex of the path is same then it will be an Eulerian
circuit.
Source
https://www.geeksforgeeks.org/eulerian-path-undirected-graph/
1051
Chapter 144
Input : n = 3
Output : 5
Explanation :
Fib(n + 2) = Fib(5) = 5
Input : n = 2
Output : 3
A Fibonacci Cube Graph is similar to hypercube graph, but with a fibonacci number of
vertices. In fibonacci cube graph only 1 vertex has degree n rest all has degree less than n.
Fibonacci cube graph of order n has F(n + 2) vertices, where F(n) is a n-th fibonacci number,
Fibonacii series : 1, 1, 2, 3, 5, 8, 13, 21, 34……………….
1052
Chapter 144. Fibonacci Cube Graph
For input n as order of graph, find the corresponding fibonacci number at the position n +
2.
where F(n) = F(n – 1) + F(n – 2)
Approach : Find the (n + 2)-th fibonacci number.
Below is the implementation of above approach :
C++
1053
Chapter 144. Fibonacci Cube Graph
}
// driver program
int main()
{
// n is the order of the graph
int n = 3;
cout << findVertices(n);
return 0;
}
Java
C#
1054
Chapter 144. Fibonacci Cube Graph
using System;
class GFG {
// function to find fibonacci number
static int fib(int n)
{
if (n <= 1)
return n;
return fib(n - 1) + fib(n - 2);
}
// function for finding number of
// vertices in fibonacci cube graph
static int findVertices (int n)
{
// return fibonacci number for
// f(n + 2)
return fib(n + 2);
}
// Driver code
static void Main()
{
// n is the order of the graph
int n = 3;
Console.Write(findVertices(n));
}
}
// This code is contributed by Sam007
PHP
<?php
// PHP code to find vertices in a
// fibonacci cube graph of order n
// function to find fibonacci number
function fib($n)
{
if ($n <= 1)
return $n;
return fib($n - 1) + fib($n - 2);
}
1055
Chapter 144. Fibonacci Cube Graph
// function for finding number of
// vertices in fibonacci cube graph
function findVertices ($n)
{
// return fibonacci number
// for f(n + 2)
return fib($n + 2);
}
// Driver Code
// n is the order of the graph
$n = 3;
echo findVertices($n);
// This code is contributed by Sam007
?>
Output :
Note that the above code can be optimized to work in O(Log n) using efficient implementa-
tions discussed in Program for Fibonacci numbers
Improved By : Sam007
Source
https://www.geeksforgeeks.org/fibonacci-cube-graph/
1056
Chapter 145
There can be more than one mother vertices in a graph. We need to output anyone of them.
For example, in the below graph, vertices 0, 1 and 2 are mother vertices.
We strongly recommend you to minimize your browser and try this yourself
first.
How to find mother vertex?
1057
Chapter 145. Find a Mother Vertex in a Graph
• Case 1:- Undirected Connected Graph : In this case, all the vertices are mother
vertices as we can reach to all the other nodes in the graph.
• Case 2:- Undirected/Directed Disconnected Graph : In this case, there is no
mother vertices as we cannot reach to all the other nodes in the graph.
• Case 3:- Directed Connected Graph : In this case, we have to find a vertex -v
in the graph such that we can reach to all the other nodes in the graph through a
directed path.
A Naive approach :
A trivial approach will be to perform a DFS/BFS on all the vertices and find whether we
can reach all the vertices from that vertex. This approach takes O(V(E+V)) time, which is
very inefficient for large graphs.
Can we do better?
We can find a mother vertex in O(V+E) time. The idea is based on Kosaraju’s Strongly
Connected Component Algorithm. In a graph of strongly connected components, mother
vertices are always vertices of source component in component graph. The idea is based on
below fact.
If there exist mother vertex (or vertices), then one of the mother vertices is the last finished
vertex in DFS. (Or a mother vertex has the maximum finish time in DFS traversal).
A vertex is said to be finished in DFS if a recursive call for its DFS is over, i.e., all descendants
of the vertex have been visited.
How does the above idea work?
Let the last finished vertex be v. Basically, we need to prove that there cannot be an
edge from another vertex u to v if u is not another mother vertex (Or there cannot exist a
non-mother vertex u such that u-→v is an edge). There can be two possibilities.
1. Recursive DFS call is made for u before v. If an edge u-→v exists, then v must have
finished before u because v is reachable through u and a vertex finishes after all its
descendants.
2. Recursive DFS call is made for v before u. In this case also, if an edge u-→v exists,
then either v must finish before u (which contradicts our assumption that v is finished
at the end) OR u should be reachable from v (which means u is another mother
vertex).
Algorithm :
1. Do DFS traversal of the given graph. While doing traversal keep track of last finished
vertex ‘v’. This step takes O(V+E) time.
2. If there exist mother vertex (or vetices), then v must be one (or one of them). Check
if v is a mother vertex by doing DFS/BFS from v. This step also takes O(V+E) time.
1058
Chapter 145. Find a Mother Vertex in a Graph
1059
Chapter 145. Find a Mother Vertex in a Graph
1060
Chapter 145. Find a Mother Vertex in a Graph
return 0;
}
Python
1061
Chapter 145. Find a Mother Vertex in a Graph
# If there exist mother vertex (or vetices) in given
# graph, then v must be one (or one of them)
# Now check if v is actually a mother vertex (or graph
# has a mother vertex). We basically check if every vertex
# is reachable from v or not.
# Reset all values in visited[] as false and do
# DFS beginning from v to check if all vertices are
# reachable from it or not.
visited = [False]*(self.V)
self.DFSUtil(v, visited)
if any(i == False for i in visited):
return -1
else:
return v
# Create a graph given in the above diagram
g = Graph(7)
g.addEdge(0, 1)
g.addEdge(0, 2)
g.addEdge(1, 3)
g.addEdge(4, 1)
g.addEdge(6, 4)
g.addEdge(5, 6)
g.addEdge(5, 2)
g.addEdge(6, 0)
print "A mother vertex is " + str(g.findMother())
# This code is contributed by Neelam Yadav
Output :
A mother vertex is 5
Source
https://www.geeksforgeeks.org/find-a-mother-vertex-in-a-graph/
1062
Chapter 146
Find all reachable nodes from every node present in a given set - GeeksforGeeks
Given an undirected graph and a set of vertices, find all reachable nodes from every vertex
present in the given set.
Consider below undirected graph with 2 disconnected components.
arr[] = {1 , 2 , 5}
Reachable nodes from 1 are 1, 2, 3, 4
Reachable nodes from 2 are 1, 2, 3, 4
Reachable nodes from 5 are 5, 6, 7
Method 1 (Simple)
One straight forward solution is to do a BFS traversal for every node present in the set and
then find all the reachable nodes.
1063
Chapter 146. Find all reachable nodes from every node present in a given set
Assume that we need to find reachable nodes for n nodes, the time complexity for this
solution would be O(n*(V+E)) where V is number of nodes in the graph and E is number
of edges in the graph. Please note that we need to call BFS as a separate call for every node
without using the visited array of previous traversals because a same vertex may need to be
printed multiple times. This seems to be an effective solution but consider the case when E
= Θ(V2 ) and n = V, time complexity becomes O(V3 ).
Method 2 (Efficient)
Since the given graph is undirected, all vertices that belong to same component have same set
of reachable nodes. So we keep track of vertex and component mappings. Every component
in the graph is assigned a number and every vertex in this component is assigned this
number. We use the visit array for this purpose, the array which is used to keep track of
visited vertices in BFS.
For a node u,
if visit[u] is 0 then
u has not been visited before
else // if not zero then
visit[u] represents the component number.
To store the reachable nodes, use a map m with key as component number and value as a
vector which stores all the reachable nodes.
To find reachable nodes for a node u return m[visit[u]]
Look at the pseudo code below in order to understand how to assign component numbers.
componentNum = 0
for i=1 to n
If visit[i] is NOT 0 then
componentNum++
For the graph shown in the example the visit array would be.
1064
Chapter 146. Find all reachable nodes from every node present in a given set
For the nodes 1, 2, 3 and 4 the component number is 1. For nodes 5, 6 and 7 the component
number is 2.
C++ Implementation of above idea
1065
Chapter 146. Find all reachable nodes from every node present in a given set
1066
Chapter 146. Find all reachable nodes from every node present in a given set
cout << endl;
}
// Find all the reachable nodes for every element
// in the arr
void findReachableNodes(Graph g, int arr[], int n)
{
// Get the number of nodes in the graph
int V = g.V;
// Take a integer visited array and initialize
// all the elements with 0
int visited[V+1];
memset(visited, 0, sizeof(visited));
// Map to store list of reachable Nodes for a
// given node.
unordered_map <int, vector<int> > m;
// Initialize component Number with 0
int componentNum = 0;
// For each node in arr[] find reachable
// Nodes
for (int i = 0 ; i < n ; i++)
{
int u = arr[i];
// Visit all the nodes of the component
if (!visited[u])
{
componentNum++;
// Store the reachable Nodes corresponding to
// the node 'i'
m[visited[u]] = g.BFS(componentNum, u, visited);
}
// At this point, we have all reachable nodes
// from u, print them by doing a look up in map m.
cout << "Reachable Nodes from " << u <<" are\n";
displayReachableNodes(visited[u], m);
}
}
// Driver program to test above functions
int main()
1067
Chapter 146. Find all reachable nodes from every node present in a given set
{
// Create a graph given in the above diagram
int V = 7;
Graph g(V);
g.addEdge(1, 2);
g.addEdge(2, 3);
g.addEdge(3, 4);
g.addEdge(3, 1);
g.addEdge(5, 6);
g.addEdge(5, 7);
// For every ith element in the arr
// find all reachable nodes from query[i]
int arr[] = {2, 4, 5};
// Find number of elements in Set
int n = sizeof(arr)/sizeof(int);
findReachableNodes(g, arr, n);
return 0;
}
Output:
Source
https://www.geeksforgeeks.org/find-all-reachable-nodes-from-every-node-present-in-a-given-set/
1068
Chapter 147
Find alphabetical order such that words can be considered sorted - GeeksforGeeks
Given an array of words, find any alphabetical order in the English alphabet such that the
given words can be considered sorted (increasing), if there exists such an order, otherwise
output impossible.
Examples:
Naive approach: The brute-force approach would be to check all the possible orders, and
check if any of them satisfy the given order of words. Considering there are 26 alphabets
in the English language, there are 26! number of permutations that can be valid orders.
Considering we check every pair for verifying an order, the complexity of this approach goes
to O(26!*N^2), which is well beyond practically preferred time complexity.
1069
Chapter 147. Find alphabetical order such that words can be considered sorted
Using topological sort: This solution requires knowledge of Graphs and its representation
as adjacency lists, DFS and Topological sorting.
In our required order, it is required to print letters such that each letter must be followed by
the letters that are placed in lower priority than them. It seems somewhat similar to what
topological sort is defined as – In topological sorting, we need to print a vertex before its
adjacent vertices. Let’s define each letter in the alphabet as nodes in a standard directed
graph. A is said to be connected to B (A—>B) if A precedes B in the order. The algorithm
can be formulated as follows:
1070
Chapter 147. Find alphabetical order such that words can be considered sorted
1071
Chapter 147. Find alphabetical order such that words can be considered sorted
1072
Chapter 147. Find alphabetical order such that words can be considered sorted
return;
}
for (int i = 0; i < out.size(); ++i)
cout << out[i];
}
// Driver code
int main()
{
vector<string> v{ "efgh", "abcd" };
findOrder(v);
return 0;
}
Output :
zyxwvutsrqponmlkjihgfeadcb
The complexity of this approach is O(N*S) + O(V+E), where V=26 (number of nodes is
the same as number of alphabets) and E<N (since at most 1 edge is created for each word
as input). Hence overall complexity is O(N*S+N). S represents the length of each word.
Source
https://www.geeksforgeeks.org/find-alphabetical-order-such-that-words-can-be-considered-sorted/
1073
Chapter 148
1074
Chapter 148. Find if an array of strings can be chained to form a circle Set 1
The idea is to create a directed graph of all characters and then find if their is an eulerian
circuit in the graph or not.
Graph representation of some string arrays are given in below diagram,
1075
Chapter 148. Find if an array of strings can be chained to form a circle Set 1
// A class that represents an undirected graph
class Graph
{
int V; // No. of vertices
list<int> *adj; // A dynamic array of adjacency lists
int *in;
public:
// Constructor and destructor
Graph(int V);
~Graph() { delete [] adj; delete [] in; }
// function to add an edge to graph
void addEdge(int v, int w) { adj[v].push_back(w); (in[w])++; }
// Method to check if this graph is Eulerian or not
bool isEulerianCycle();
// Method to check if all non-zero degree vertices are connected
bool isSC();
// Function to do DFS starting from v. Used in isConnected();
void DFSUtil(int v, bool visited[]);
Graph getTranspose();
};
Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V];
in = new int[V];
for (int i = 0; i < V; i++)
in[i] = 0;
}
/* This function returns true if the directed graph has an eulerian
cycle, otherwise returns false */
bool Graph::isEulerianCycle()
{
// Check if all non-zero degree vertices are connected
if (isSC() == false)
return false;
// Check if in degree and out degree of every vertex is same
for (int i = 0; i < V; i++)
if (adj[i].size() != in[i])
return false;
1076
Chapter 148. Find if an array of strings can be chained to form a circle Set 1
return true;
}
// A recursive function to do DFS starting from v
void Graph::DFSUtil(int v, bool visited[])
{
// Mark the current node as visited and print it
visited[v] = true;
// Recur for all the vertices adjacent to this vertex
list<int>::iterator i;
for (i = adj[v].begin(); i != adj[v].end(); ++i)
if (!visited[*i])
DFSUtil(*i, visited);
}
// Function that returns reverse (or transpose) of this graph
// This function is needed in isSC()
Graph Graph::getTranspose()
{
Graph g(V);
for (int v = 0; v < V; v++)
{
// Recur for all the vertices adjacent to this vertex
list<int>::iterator i;
for(i = adj[v].begin(); i != adj[v].end(); ++i)
{
g.adj[*i].push_back(v);
(g.in[v])++;
}
}
return g;
}
// This function returns true if all non-zero degree vertices of
// graph are strongly connected. Please refer
// https://www.geeksforgeeks.org/connectivity-in-a-directed-graph/
bool Graph::isSC()
{
// Mark all the vertices as not visited (For first DFS)
bool visited[V];
for (int i = 0; i < V; i++)
visited[i] = false;
// Find the first vertex with non-zero degree
int n;
for (n = 0; n < V; n++)
1077
Chapter 148. Find if an array of strings can be chained to form a circle Set 1
1078
Chapter 148. Find if an array of strings can be chained to form a circle Set 1
Python
1079
Chapter 148. Find if an array of strings can be chained to form a circle Set 1
# Do DFS traversal starting from first non zero degree vertex.
self.DFSUtil(n, visited)
# If DFS traversal doesn't visit all vertices, then return false.
for i in xrange(self.V):
if len(self.adj[i]) > 0 and visited[i] == False:
return False
# Create a reversed graph
gr = self.getTranspose()
# Mark all the vertices as not visited (For second DFS)
for i in xrange(self.V):
visited[i] = False
# Do DFS for reversed graph starting from first vertex.
# Staring Vertex must be same starting point of first DFS
gr.DFSUtil(n, visited)
# If all vertices are not visited in second DFS, then
# return false
for i in xrange(self.V):
if len(self.adj[i]) > 0 and visited[i] == False:
return False
return True
# This function returns true if the directed graph has an eulerian
# cycle, otherwise returns false
def isEulerianCycle(self):
# Check if all non-zero degree vertices are connected
if self.isSC() == False:
return False
# Check if in degree and out degree of every vertex is same
for i in xrange(self.V):
if len(self.adj[i]) != self.inp[i]:
return False
return True
# A recursive function to do DFS starting from v
def DFSUtil(self, v, visited):
# Mark the current node as visited and print it
visited[v] = True
1080
Chapter 148. Find if an array of strings can be chained to form a circle Set 1
1081
Chapter 148. Find if an array of strings can be chained to form a circle Set 1
# This code is contributed by BHAVYA JAIN
Output:
Can be chained
Can't be chained
Source
https://www.geeksforgeeks.org/given-array-strings-find-strings-can-chained-form-circle/
1082
Chapter 149
1083
Chapter 149. Find if an array of strings can be chained to form a circle Set 2
Now it can be clearly seen after graph representation that if a loop among graph vertices
is possible then we can reorder the strings otherwise not. As in above diagram’s example a
loop can be found in first and third array of string but not in second array of string. Now
to check whether this graph can have a loop which goes through all the vertices,
we’ll check two conditions,
1) Indegree and Outdegree of each vertex should be same.
2) Graph should be strongly connected.
First condition can be checked easily by keeping two arrays, in and out for each character.
For checking whether graph is having a loop which goes through all vertices is same as
checking complete directed graph is strongly connected or not because if it has a loop which
goes through all vertices then we can reach to any vertex from any other vertex that is,
graph will be strongly connected and same argument can be given for reverse statement
also.
Now for checking second condition we will just run a DFS from any character and visit all
reachable vertices from this, now if graph has a loop then after this one DFS all vertices
should be visited, if all vertices are visited then we will return true otherwise false so visiting
all vertices in a single DFS flags a possible ordering among strings.
1084
Chapter 149. Find if an array of strings can be chained to form a circle Set 2
1085
Chapter 149. Find if an array of strings can be chained to form a circle Set 2
// Initialize indegree and outdegree of every
// vertex as 0.
vector<int> in(M, 0), out(M, 0);
// Process all strings one by one
for (int i = 0; i < N; i++)
{
// Find first and last characters
int f = arr[i].front() - 'a';
int l = arr[i].back() - 'a';
// Mark the characters
mark[f] = mark[l] = true;
// increase indegree and outdegree count
in[f]++;
out[l]++;
// Add an edge in graph
g[f].push_back(l);
}
// If for any character indegree is not equal to
// outdegree then ordering is not possible
for (int i = 0; i < M; i++)
if (in[i] != out[i])
return false;
return isConnected(g, mark, arr[0].front() - 'a');
}
// Driver code to test above methods
int main()
{
// string arr[] = {"abc", "efg", "cde", "ghi", "ija"};
string arr[] = {"ab", "bc", "cd", "de", "ed", "da"};
int N = sizeof(arr) / sizeof(arr[0]);
if (possibleOrderAmongString(arr, N) == false)
cout << "Ordering not possible\n";
else
cout << "Ordering is possible\n";
return 0;
}
Output:
1086
Chapter 149. Find if an array of strings can be chained to form a circle Set 2
Ordering is possible
Source
https://www.geeksforgeeks.org/find-array-strings-can-chained-form-circle-set-2/
1087
Chapter 150
Input : Source s = 0, k = 58
Output : True
There exists a simple path 0 -> 7 -> 1
-> 2 -> 8 -> 6 -> 5 -> 3 -> 4
Which has a total distance of 60 km which
is more than 58.
Input : Source s = 0, k = 62
Output : False
We strongly recommend you to minimize your browser and try this yourself
first.
One important thing to note is, simply doing BFS or DFS and picking the longest edge at
every step would not work. The reason is, a shorter edge can produce longer path due to
higher weight edges connected through it.
1088
Chapter 150. Find if there is a path of more than k length from a source
The idea is to use Backtracking. We start from given source, explore all paths from current
vertex. We keep track of current distance from source. If distance becomes more than k, we
return true. If a path doesn’t produces more than k distance, we backtrack.
How do we make sure that the path is simple and we don’t loop in a cycle? The idea is to
keep track of current path vertices in an array. Whenever we add a vertex to path, we check
if it already exists or not in current path. If it exists, we ignore the edge.
Below is C++ implementation of above idea.
1089
Chapter 150. Find if there is a path of more than k length from a source
// Prints shortest paths from src to all other vertices
bool Graph::pathMoreThanKUtil(int src, int k, vector<bool> &path)
{
// If k is 0 or negative, return true;
if (k <= 0)
return true;
// Get all adjacent vertices of source vertex src and
// recursively explore all paths from src.
list<iPair>::iterator i;
for (i = adj[src].begin(); i != adj[src].end(); ++i)
{
// Get adjacent vertex and weight of edge
int v = (*i).first;
int w = (*i).second;
// If vertex v is already there in path, then
// there is a cycle (we ignore this edge)
if (path[v] == true)
continue;
// If weight of is more than k, return true
if (w >= k)
return true;
// Else add this vertex to path
path[v] = true;
// If this adjacent can provide a path longer
// than k, return true.
if (pathMoreThanKUtil(v, k-w, path))
return true;
// Backtrack
path[v] = false;
}
// If no adjacent could produce longer path, return
// false
return false;
}
// Allocates memory for adjacency list
Graph::Graph(int V)
{
this->V = V;
adj = new list<iPair> [V];
1090
Chapter 150. Find if there is a path of more than k length from a source
}
// Utility function to an edge (u, v) of weight w
void Graph::addEdge(int u, int v, int w)
{
adj[u].push_back(make_pair(v, w));
adj[v].push_back(make_pair(u, w));
}
// Driver program to test methods of graph class
int main()
{
// create the graph given in above fugure
int V = 9;
Graph g(V);
// making above shown graph
g.addEdge(0, 1, 4);
g.addEdge(0, 7, 8);
g.addEdge(1, 2, 8);
g.addEdge(1, 7, 11);
g.addEdge(2, 3, 7);
g.addEdge(2, 8, 2);
g.addEdge(2, 5, 4);
g.addEdge(3, 4, 9);
g.addEdge(3, 5, 14);
g.addEdge(4, 5, 10);
g.addEdge(5, 6, 2);
g.addEdge(6, 7, 1);
g.addEdge(6, 8, 6);
g.addEdge(7, 8, 7);
int src = 0;
int k = 62;
g.pathMoreThanK(src, k)? cout << "Yes\n" :
cout << "No\n";
k = 60;
g.pathMoreThanK(src, k)? cout << "Yes\n" :
cout << "No\n";
return 0;
}
Output:
No
Yes
1091
Chapter 150. Find if there is a path of more than k length from a source
Exercise:
Modify the above solution to find weight of longest path from a given source.
Time Complexity: O(n!)
Explanation:
From the source node, we one-by-one visit all the paths and check if the total weight is
greater than k for each path. So, the worst case will be when the number of possible paths
is maximum. This is the case when every node is connected to every other node.
Beginning from the source node we have n-1 adjacent nodes. The time needed for a path to
connect any two nodes is 2. One for joining the source and the next adjacent vertex. One
for breaking the connection between the source and the old adjacent vertex.
After selecting a node out of n-1 adjacent nodes, we are left with n-2 adjacent nodes (as the
source node is already included in the path) and so on at every step of selecting a node our
problem reduces by 1 node.
We can write this in the form of a recurrence relation as: F(n) = n*(2+F(n-1))
This expands to: 2n + 2n*(n-1) + 2n*(n-1)*(n-2) + ……. + 2n(n-1)(n-2)(n-3)…..1
As n times 2n(n-1)(n-2)(n-3)….1 is greater than the given expression so we can safely say
time complexity is: n*2*n!
Here in the question the first node is defined so time complexity becomes
F(n-1) = 2(n-1)*(n-1)! = 2*n*(n-1)! – 2*1*(n-1)! = 2*n!-2*(n-1)! = O(n!)
This article is contributed by Shivam Gupta. The explanation for time complexity is
contributed by Pranav Nambiar. Please write comments if you find anything incorrect,
or you want to share more information about the topic discussed above
Source
https://www.geeksforgeeks.org/find-if-there-is-a-path-of-more-than-k-length-from-a-source/
1092
Chapter 151
We strongly recommend you to minimize your browser and try this yourself
first.
The standard algorithm to find a k-core graph is to remove all the vertices that have degree
less than- ‘K’ from the input graph. We must be careful that removing a vertex reduces the
degree of all the vertices adjacent to it, hence the degree of adjacent vertices can also drop
below-‘K’. And thus, we may have to remove those vertices also. This process may/may not
go until there are no vertices left in the graph.
To implement above algorithm, we do a modified DFS on the input graph and delete all the
vertices having degree less than ‘K’, then update degrees of all the adjacent vertices, and if
their degree falls below ‘K’ we will delete them too.
Below is implementation of above idea. Note that the below program only prints vertices
of k cores, but it can be easily extended to print the complete k cores as we have modified
1093
Chapter 151. Find k-cores of an undirected graph
adjacency list.
C/C++
1094
Chapter 151. Find k-cores of an undirected graph
// If adjacent is not processed, process it
if (!visited[*i])
{
// If degree of adjacent after processing becomes
// less than k, then reduce degree of v also.
if (DFSUtil(*i, visited, vDegree, k))
vDegree[v]--;
}
}
// Return true if degree of v is less than k
return (vDegree[v] < k);
}
Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V];
}
void Graph::addEdge(int u, int v)
{
adj[u].push_back(v);
adj[v].push_back(u);
}
// Prints k cores of an undirected graph
void Graph::printKCores(int k)
{
// INITIALIZATION
// Mark all the vertices as not visited and not
// processed.
vector<bool> visited(V, false);
vector<bool> processed(V, false);
int mindeg = INT_MAX;
int startvertex;
// Store degrees of all vertices
vector<int> vDegree(V);
for (int i=0; i<V; i++)
{
vDegree[i] = adj[i].size();
if (vDegree[i] < mindeg)
{
mindeg = vDegree[i];
1095
Chapter 151. Find k-cores of an undirected graph
startvertex=i;
}
}
DFSUtil(startvertex, visited, vDegree, k);
// DFS traversal to update degrees of all
// vertices.
for (int i=0; i<V; i++)
if (visited[i] == false)
DFSUtil(i, visited, vDegree, k);
// PRINTING K CORES
cout << "K-Cores : \n";
for (int v=0; v<V; v++)
{
// Only considering those vertices which have degree
// >= K after BFS
if (vDegree[v] >= k)
{
cout << "\n[" << v << "]";
// Traverse adjacency list of v and print only
// those adjacent which have vDegree >= k after
// BFS.
list<int>::iterator itr;
for (itr = adj[v].begin(); itr != adj[v].end(); ++itr)
if (vDegree[*itr] >= k)
cout << " -> " << *itr;
}
}
}
// Driver program to test methods of graph class
int main()
{
// Create a graph given in the above diagram
int k = 3;
Graph g1(9);
g1.addEdge(0, 1);
g1.addEdge(0, 2);
g1.addEdge(1, 2);
g1.addEdge(1, 5);
g1.addEdge(2, 3);
g1.addEdge(2, 4);
g1.addEdge(2, 5);
g1.addEdge(2, 6);
g1.addEdge(3, 4);
1096
Chapter 151. Find k-cores of an undirected graph
g1.addEdge(3, 6);
g1.addEdge(3, 7);
g1.addEdge(4, 6);
g1.addEdge(4, 7);
g1.addEdge(5, 6);
g1.addEdge(5, 8);
g1.addEdge(6, 7);
g1.addEdge(6, 8);
g1.printKCores(k);
cout << endl << endl;
Graph g2(13);
g2.addEdge(0, 1);
g2.addEdge(0, 2);
g2.addEdge(0, 3);
g2.addEdge(1, 4);
g2.addEdge(1, 5);
g2.addEdge(1, 6);
g2.addEdge(2, 7);
g2.addEdge(2, 8);
g2.addEdge(2, 9);
g2.addEdge(3, 10);
g2.addEdge(3, 11);
g2.addEdge(3, 12);
g2.printKCores(k);
return 0;
}
Python
1097
Chapter 151. Find k-cores of an undirected graph
self.graph[v].append(u)
# A recursive function to call DFS starting from v.
# It returns true if vDegree of v after processing is less
# than k else false
# It also updates vDegree of adjacent if vDegree of v
# is less than k. And if vDegree of a processed adjacent
# becomes less than k, then it reduces of vDegree of v also,
def DFSUtil(self,v,visited,vDegree,k):
# Mark the current node as visited
visited[v] = True
# Recur for all the vertices adjacent to this vertex
for i in self.graph[v]:
# vDegree of v is less than k, then vDegree of
# adjacent must be reduced
if vDegree[v] < k:
vDegree[i] = vDegree[i] - 1
# If adjacent is not processed, process it
if visited[i]==False:
# If vDegree of adjacent after processing becomes
# less than k, then reduce vDegree of v also
if (self.DFSUtil(i,visited,vDegree,k)):
vDegree[v]-=1
# Return true if vDegree of v is less than k
return vDegree[v] < k
# Prints k cores of an undirected graph
def printKCores(self,k):
# INITIALIZATION
# Mark all the vertices as not visited
visited = [False]*self.V
# Store vDegrees of all vertices
vDegree = [0]*self.V
for i in self.graph:
vDegree[i]=len(self.graph[i])
# choose any vertex as starting vertex
self.DFSUtil(0,visited,vDegree,k)
1098
Chapter 151. Find k-cores of an undirected graph
1099
Chapter 151. Find k-cores of an undirected graph
g2.addEdge(1, 5)
g2.addEdge(1, 6)
g2.addEdge(2, 7)
g2.addEdge(2, 8)
g2.addEdge(2, 9)
g2.addEdge(3, 10)
g2.addEdge(3, 11)
g2.addEdge(3, 12)
g2.printKCores(k)
# This code is contributed by Neelam Yadav
Output :
K-Cores :
K-Cores :
Time complexity of the above solution is O(V + E) where V is number of vertices and E
is number of edges.
Related Concepts :
Degeneracy : Degeneracy of a graph is the largest value k such that the graph has a k-core.
For example, the above shown graph has a 3-Cores and doesn’t have 4 or higher cores.
Therefore, above graph is 3-degenerate.
Degeneracy of a graph is used to measure how sparse graph is.
Reference :
https://en.wikipedia.org/wiki/Degeneracy_%28graph_theory%29
This article is contributed by Rachit Belwariar. Please write comments if you find any-
thing incorrect, or you want to share more information about the topic discussed above
Improved By : brainiac
Source
https://www.geeksforgeeks.org/find-k-cores-graph/
1100
Chapter 152
Input : M[][5] = { 0 0 1 1 0
1 0 1 1 0
0 1 0 0 0
0 0 0 0 1 }
Output : 6
Ex: in the following example, there are 2 regions one with length 1 and the other as 6.
so largest region : 6
1101
Chapter 152. Find length of the largest region in Boolean Matrix
#define ROW 4
#define COL 5
// A function to check if a given cell (row, col)
// can be included in DFS
int isSafe(int M[][COL], int row, int col,
bool visited[][COL])
{
// row number is in range, column number is in
// range and value is 1 and not yet visited
return (row >= 0) && (row < ROW) &&
(col >= 0) && (col < COL) &&
(M[row][col] && !visited[row][col]);
}
// A utility function to do DFS for a 2D boolean
// matrix. It only considers the 8 neighbours as
// adjacent vertices
void DFS(int M[][COL], int row, int col,
bool visited[][COL], int &count)
{
// These arrays are used to get row and column
// numbers of 8 neighbours of a given cell
static int rowNbr[] = {-1, -1, -1, 0, 0, 1, 1, 1};
static int colNbr[] = {-1, 0, 1, -1, 1, -1, 0, 1};
// Mark this cell as visited
visited[row][col] = true;
// Recur for all connected neighbours
for (int k = 0; k < 8; ++k)
{
if (isSafe(M, row + rowNbr[k], col + colNbr[k],
visited))
{
// increment region length by one
count++;
DFS(M, row + rowNbr[k], col + colNbr[k],
visited, count);
}
}
}
// The main function that returns largest length region
// of a given boolean 2D matrix
int largestRegion(int M[][COL])
{
// Make a bool array to mark visited cells.
1102
Chapter 152. Find length of the largest region in Boolean Matrix
Output:
1103
Chapter 152. Find length of the largest region in Boolean Matrix
Source
https://www.geeksforgeeks.org/find-length-largest-region-boolean-matrix/
1104
Chapter 153
The idea is to use shortest path algorithm. We one by one remove every edge from graph,
then we find shortest path between two corner vertices of it. We add an edge back before
we process next edge.
1105
Chapter 153. Find minimum weight cycle in an undirected graph
1106
Chapter 153. Find minimum weight cycle in an undirected graph
1107
Chapter 153. Find minimum weight cycle in an undirected graph
// a vertex
list< pair<int, int> >::iterator i;
for (i = adj[u].begin(); i != adj[u].end(); ++i)
{
// Get vertex label and weight of current adjacent
// of u.
int v = (*i).first;
int weight = (*i).second;
// If there is uhorter path to v through u.
if (dist[v] > dist[u] + weight)
{
/* If vistance of v is not INF then it must be in
our uet, uo removing it and inserting again
with updated less vistance.
Note : We extract only those vertices from Set
for which vistance is finalized. So for them,
we would never reach here. */
if (dist[v] != INF)
setds.erase(setds.find(make_pair(dist[v], v)));
// Updating vistance of v
dist[v] = dist[u] + weight;
setds.insert(make_pair(dist[v], v));
}
}
}
// return uhortest path from current uource to uink
return dist[v] ;
}
// function return minimum weighted cycle
int Graph :: FindMinimumCycle ( )
{
int min_cycle = INT_MAX;
int E = edge.size();
for ( int i = 0 ; i < E ; i++ )
{
// current Edge information
Edge e = edge[i];
// get current edge vertices which we currently
// remove from graph and then find uhortest path
// between these two vertex using Dijkstra’s
// uhortest path algorithm .
removeEdge( e.u, e.v, e.weight ) ;
1108
Chapter 153. Find minimum weight cycle in an undirected graph
Output:
14
1109
Chapter 153. Find minimum weight cycle in an undirected graph
Source
https://www.geeksforgeeks.org/find-minimum-weight-cycle-undirected-graph/
1110
Chapter 154
Input:
O O O O G
O W W O O
O O O W O
G W W W O
O O O O G
Output:
3 3 2 1 0
2 -1 -1 2 1
1 2 3 -1 2
0 -1 -1 -1 1
1 2 2 1 0
1111
Chapter 154. Find Shortest distance from a guard in a Bank
The idea is to do BFS. We first enqueue all cells containing the guards and loop till queue
is not empty. For each iteration of the loop, we dequeue the front cell from the queue and
for each of its four adjacent cells, if cell is an open area and its distance from guard is not
calculated yet, we update its distance and enqueue it. Finally after BFS procedure is over,
we print the distance matrix.
Below is C++ implementation of above idea –
1112
Chapter 154. Find Shortest distance from a guard in a Bank
}
// Function to replace all of the O's in the matrix
// with their shortest distance from a guard
void findDistance(char matrix[][N])
{
int output[M][N];
queue<queueNode> q;
// finding Guards location and adding into queue
for (int i = 0; i < M; i++)
{
for (int j = 0; j < N; j++)
{
// initialize each cell as -1
output[i][j] = -1;
if (matrix[i][j] == 'G')
{
queueNode pos = {i, j, 0};
q.push(pos);
// guard has 0 distance
output[i][j] = 0;
}
}
}
// do till queue is empty
while (!q.empty())
{
// get the front cell in the queue and update
// its adjacent cells
queueNode curr = q.front();
int x = curr.i, y = curr.j, dist = curr.distance;
// do for each adjacent cell
for (int i = 0; i < 4; i++)
{
// if adjacent cell is valid, has path and
// not visited yet, en-queue it.
if (isSafe(x + row[i], y + col[i], matrix, output)
&& isValid(x + row[i], y + col[i]))
{
output[x + row[i]][y + col[i]] = dist + 1;
queueNode pos = {x + row[i], y + col[i], dist + 1};
q.push(pos);
}
}
1113
Chapter 154. Find Shortest distance from a guard in a Bank
// dequeue the front cell as its distance is found
q.pop();
}
// print output matrix
for (int i = 0; i < M; i++)
{
for (int j = 0; j < N; j++)
cout << std::setw(3) << output[i][j];
cout << endl;
}
}
// Driver code
int main()
{
char matrix[][N] =
{
{'O', 'O', 'O', 'O', 'G'},
{'O', 'W', 'W', 'O', 'O'},
{'O', 'O', 'O', 'W', 'O'},
{'G', 'W', 'W', 'W', 'O'},
{'O', 'O', 'O', 'O', 'G'}
};
findDistance(matrix);
return 0;
}
Output:
3 3 2 1 0
2 -1 -1 2 1
1 2 3 -1 2
0 -1 -1 -1 1
1 2 2 1 0
Source
https://www.geeksforgeeks.org/find-shortest-distance-guard-bank/
1114
Chapter 155
0-----1
|\ |
| \ |
| \|
2-----3
Input : ver = 0
Output : 3
Input : ver = 1
Output : 2
Algorithm:-
1115
Chapter 155. Find the Degree of a Particular vertex in a Graph
1116
Chapter 155. Find the Degree of a Particular vertex in a Graph
| \ |
| \ |
2-----3 */
//direction from 0
G->dir[0][1]=1;
G->dir[0][2]=1;
G->dir[0][3]=1;
//direction from 1
G->dir[1][0]=1;
G->dir[1][3]=1;
//direction from 2
G->dir[2][0]=1;
G->dir[2][3]=1;
//direction from 3
G->dir[3][0]=1;
G->dir[3][1]=1;
G->dir[3][2]=1;
return G;
}
// Driver code
int main()
{
int vertices = 4;
int edges = 5;
struct graph *G = createGraph(vertices, edges);
// loc is find the degree of
// particular vertex
int ver = 0;
int degree = findDegree(G, ver);
cout << degree << "\n";
return 0;
}
Java
1117
Chapter 155. Find the Degree of a Particular vertex in a Graph
{
//Structure of Graph
static class Graph
{
// vertices and edges
int v, e;
int[][] dir;
//Graph Constructor
Graph(int v, int e) {
this.v = v;
this.e = e;
dir = new int[v][];
for (int i = 0; i < v; i++)
dir[i] = new int[v];
}
}
static Graph createGraph(int v, int e)
{
Graph G = new Graph(v, e);
/* 0-----1
| \ |
| \ |
| \ |
2-----3 */
//direction from 0
G.dir[0][1] = 1;
G.dir[0][2] = 1;
G.dir[0][3] = 1;
//direction from 1
G.dir[1][0] = 1;
G.dir[1][3] = 1;
//direction from 2
G.dir[2][0] = 1;
G.dir[2][3] = 1;
//direction from 3
G.dir[3][0] = 1;
G.dir[3][1] = 1;
G.dir[3][2] = 1;
return G;
}
1118
Chapter 155. Find the Degree of a Particular vertex in a Graph
Output:
Source
https://www.geeksforgeeks.org/find-degree-particular-vertex-graph/
1119
Chapter 156
Find the minimum number of moves needed to move from one cell of matrix to another -
GeeksforGeeks
Given a N X N matrix (M) filled with 1 , 0 , 2 , 3 . Find the minimum numbers of moves
needed to move from source to destination (sink) . while traversing through blank cells only.
You can traverse up, down, right and left.
A value of cell 1 means Source.
A value of cell 2 means Destination.
A value of cell 3 means Blank cell.
A value of cell 0 means Blank Wall.
Note : there is only single source and single destination.they may be more than one path
from source to destination(sink).each move in matrix we consider as ‘1’
Examples:
Input : M[3][3] = {{ 0 , 3 , 2 },
{ 3 , 3 , 0 },
{ 1 , 3 , 0 }};
Output : 4
Input : M[4][4] = {{ 3 , 3 , 1 , 0 },
{ 3 , 0 , 3 , 3 },
{ 2 , 3 , 0 , 3 },
{ 0 , 3 , 3 , 3 }};
Output : 4
1120
Chapter 156. Find the minimum number of moves needed to move from one cell of matrix
to another
.
The idea is to use Level graph ( Breadth First Traversal ). Consider each cell as a node
and each boundary between any two adjacent cells be an edge . so total number of Node is
N*N.
1121
Chapter 156. Find the minimum number of moves needed to move from one cell of matrix
to another
1122
Chapter 156. Find the minimum number of moves needed to move from one cell of matrix
to another
{
// Else, continue to do BFS
if (level[*i] < 0 || level[*i] > level[s] + 1 )
{
level[*i] = level[s] + 1 ;
queue.push_back(*i);
}
}
}
// return minimum moves from source to sink
return level[d] ;
}
bool isSafe(int i, int j, int M[][N])
{
if ((i < 0 || i >= N) ||
(j < 0 || j >= N ) || M[i][j] == 0)
return false;
return true;
}
// Returns minimum numbers of moves from a source (a
// cell with value 1) to a destination (a cell with
// value 2)
int MinimumPath(int M[][N])
{
int s , d ; // source and destination
int V = N*N+2;
Graph g(V);
// create graph with n*n node
// each cell consider as node
int k = 1 ; // Number of current vertex
for (int i =0 ; i < N ; i++)
{
for (int j = 0 ; j < N; j++)
{
if (M[i][j] != 0)
{
// connect all 4 adjacent cell to
// current cell
if ( isSafe ( i , j+1 , M ) )
g.addEdge ( k , k+1 );
if ( isSafe ( i , j-1 , M ) )
g.addEdge ( k , k-1 );
if (j< N-1 && isSafe ( i+1 , j , M ) )
1123
Chapter 156. Find the minimum number of moves needed to move from one cell of matrix
to another
g.addEdge ( k , k+N );
if ( i > 0 && isSafe ( i-1 , j , M ) )
g.addEdge ( k , k-N );
}
// source index
if( M[i][j] == 1 )
s = k ;
// destination index
if (M[i][j] == 2)
d = k;
k++;
}
}
// find minimum moves
return g.BFS (s, d) ;
}
// driver program to check above function
int main()
{
int M[N][N] = {{ 3 , 3 , 1 , 0 },
{ 3 , 0 , 3 , 3 },
{ 2 , 3 , 0 , 3 },
{ 0 , 3 , 3 , 3 }
};
cout << MinimumPath(M) << endl;
return 0;
}
Output:
Source
https://www.geeksforgeeks.org/find-minimum-numbers-moves-needed-move-one-cell-matrix-another/
1124
Chapter 157
This is a variation of the standard problem: “Counting the number of connected components
in an undirected graph”.
Before we go to the problem, let us understand what is a connected component. A connected
component of an undirected graph is a subgraph in which every two vertices are connected
to each other by a path(s), and which is connected to no other vertices outside the subgraph.
For example, the graph shown below has three connected components.
1125
Chapter 157. Find the number of islands Set 1 (Using DFS)
A graph where all vertices are connected with each other has exactly one connected com-
ponent, consisting of the whole graph. Such graph with only one connected component is
called as Strongly Connected Graph.
The problem can be easily solved by applying DFS() on each component. In each DFS() call,
a component or a sub-graph is visited. We will call DFS on the next un-visited component.
The number of calls to DFS() gives the number of connected components. BFS can also be
used.
What is an island?
A group of connected 1s forms an island. For example, the below matrix contains 5 islands
{1, 1, 0, 0, 0},
{0, 1, 0, 0, 1},
{1, 0, 0, 1, 1},
{0, 0, 0, 0, 0},
{1, 0, 1, 0, 1}
A cell in 2D matrix can be connected to 8 neighbours. So, unlike standard DFS(), where we
recursively call for all adjacent vertices, here we can recursively call for 8 neighbours only.
We keep track of the visited 1s so that they are not visited again.
C/C++
1126
Chapter 157. Find the number of islands Set 1 (Using DFS)
#define ROW 5
#define COL 5
// A function to check if a given cell (row, col) can be included in DFS
int isSafe(int M[][COL], int row, int col, bool visited[][COL])
{
// row number is in range, column number is in range and value is 1
// and not yet visited
return (row >= 0) && (row < ROW) &&
(col >= 0) && (col < COL) &&
(M[row][col] && !visited[row][col]);
}
// A utility function to do DFS for a 2D boolean matrix. It only considers
// the 8 neighbours as adjacent vertices
void DFS(int M[][COL], int row, int col, bool visited[][COL])
{
// These arrays are used to get row and column numbers of 8 neighbours
// of a given cell
static int rowNbr[] = {-1, -1, -1, 0, 0, 1, 1, 1};
static int colNbr[] = {-1, 0, 1, -1, 1, -1, 0, 1};
// Mark this cell as visited
visited[row][col] = true;
// Recur for all connected neighbours
for (int k = 0; k < 8; ++k)
if (isSafe(M, row + rowNbr[k], col + colNbr[k], visited) )
DFS(M, row + rowNbr[k], col + colNbr[k], visited);
}
// The main function that returns count of islands in a given boolean
// 2D matrix
int countIslands(int M[][COL])
{
// Make a bool array to mark visited cells.
// Initially all cells are unvisited
bool visited[ROW][COL];
memset(visited, 0, sizeof(visited));
// Initialize count as 0 and travese through the all cells of
// given matrix
int count = 0;
for (int i = 0; i < ROW; ++i)
for (int j = 0; j < COL; ++j)
if (M[i][j] && !visited[i][j]) // If a cell with value 1 is not
{ // visited yet, then new island found
1127
Chapter 157. Find the number of islands Set 1 (Using DFS)
Java
1128
Chapter 157. Find the number of islands Set 1 (Using DFS)
1129
Chapter 157. Find the number of islands Set 1 (Using DFS)
{1, 0, 1, 0, 1}
};
Islands I = new Islands();
System.out.println("Number of islands is: "+ I.countIslands(M));
}
} //Contributed by Aakash Hasija
Python
1130
Chapter 157. Find the number of islands Set 1 (Using DFS)
C#
// C# program to count
// islands in boolean
// 2D matrix
using System;
1131
Chapter 157. Find the number of islands Set 1 (Using DFS)
class GFG
{
// No of rows
// and columns
static int ROW = 5, COL = 5;
// A function to check if
// a given cell (row, col)
// can be included in DFS
static bool isSafe(int [,]M, int row,
int col, bool [,]visited)
{
// row number is in range,
// column number is in range
// and value is 1 and not
// yet visited
return (row >= 0) && (row < ROW) &&
(col >= 0) && (col < COL) &&
(M[row, col] == 1 &&
!visited[row, col]);
}
// A utility function to do
// DFS for a 2D boolean matrix.
// It only considers the 8
// neighbors as adjacent vertices
static void DFS(int [,]M, int row,
int col, bool [,]visited)
{
// These arrays are used to
// get row and column numbers
// of 8 neighbors of a given cell
int []rowNbr = new int[] {-1, -1, -1, 0,
0, 1, 1, 1};
int []colNbr = new int[] {-1, 0, 1, -1,
1, -1, 0, 1};
// Mark this cell
// as visited
visited[row, col] = true;
// Recur for all
// connected neighbours
for (int k = 0; k < 8; ++k)
if (isSafe(M, row + rowNbr[k], col +
colNbr[k], visited))
DFS(M, row + rowNbr[k],
1132
Chapter 157. Find the number of islands Set 1 (Using DFS)
1133
Chapter 157. Find the number of islands Set 1 (Using DFS)
PHP
<?php
// Program to count islands
// in boolean 2D matrix
$ROW = 5;
$COL = 5;
// A function to check if a
// given cell (row, col) can
// be included in DFS
function isSafe(&$M, $row, $col,
&$visited)
{
global $ROW, $COL;
// row number is in range,
// column number is in
// range and value is 1
// and not yet visited
return ($row >= 0) && ($row < $ROW) &&
($col >= 0) && ($col < $COL) &&
($M[$row][$col] &&
!isset($visited[$row][$col]));
}
// A utility function to do DFS
// for a 2D boolean matrix. It
// only considers the 8 neighbours
// as adjacent vertices
function DFS(&$M, $row, $col,
&$visited)
{
// These arrays are used to
// get row and column numbers
// of 8 neighbours of a given cell
$rowNbr = array(-1, -1, -1, 0,
0, 1, 1, 1);
$colNbr = array(-1, 0, 1, -1,
1, -1, 0, 1);
// Mark this cell as visited
$visited[$row][$col] = true;
1134
Chapter 157. Find the number of islands Set 1 (Using DFS)
1135
Chapter 157. Find the number of islands Set 1 (Using DFS)
// This code is contributed
// by ChitraNayal
?>
Output:
Source
https://www.geeksforgeeks.org/find-number-of-islands/
1136
Chapter 158
{1, 1, 0, 0, 0},
{0, 1, 0, 0, 1},
{1, 0, 0, 1, 1},
{0, 0, 0, 0, 0},
{1, 0, 1, 0, 1}
Approach:
1) Initialize result (count of islands) as 0
2) Traverse each index of the 2D matrix.
3) If value at that index is 1, check all its 8 neighbours. If a neighbour is also equal to 1,
take union of index and its neighbour.
4) Now define an array of size row*column to store frequencies of all sets.
5) Now traverse the matrix again.
1137
Chapter 158. Find the number of Islands Set 2 (Using Disjoint Set)
1138
Chapter 158. Find the number of Islands Set 2 (Using Disjoint Set)
1139
Chapter 158. Find the number of Islands Set 2 (Using Disjoint Set)
int n;
public DisjointUnionSets(int n)
{
rank = new int[n];
parent = new int[n];
this.n = n;
makeSet();
}
void makeSet()
{
// Initially, all elements are in their
// own set.
for (int i=0; i<n; i++)
parent[i] = i;
}
// Finds the representative of the set that x
// is an element of
int find(int x)
{
if (parent[x] != x)
{
// if x is not the parent of itself,
// then x is not the representative of
// its set.
// so we recursively call Find on its parent
// and move i's node directly under the
// representative of this set
return find(parent[x]);
}
return x;
}
// Unites the set that includes x and the set
// that includes y
void union(int x, int y)
{
// Find the representatives (or the root nodes)
// for x an y
int xRoot = find(x);
int yRoot = find(y);
// Elements are in the same set, no need
// to unite anything.
if (xRoot == yRoot)
1140
Chapter 158. Find the number of Islands Set 2 (Using Disjoint Set)
return;
// If x's rank is less than y's rank
// Then move x under y so that depth of tree
// remains less
if (rank[xRoot] < rank[yRoot])
parent[xRoot] = yRoot;
// Else if y's rank is less than x's rank
// Then move y under x so that depth of tree
// remains less
else if(rank[yRoot]<rank[xRoot])
parent[yRoot] = xRoot;
else // Else if their ranks are the same
{
// Then move y under x (doesn't matter
// which one goes where)
parent[yRoot] = xRoot;
// And increment the the result tree's
// rank by 1
rank[xRoot] = rank[xRoot] + 1;
}
}
}
Output:
Source
https://www.geeksforgeeks.org/find-the-number-of-islands-set-2-using-disjoint-set/
1141
Chapter 159
Input : N = 2
Output : 10
Explanation : 10 is a multiple of 2.
Note that 5 * 2 = 10
Input : N = 17
Output : 11101
Explanation : 11101 is a multiple of 17.
Note that 653 * 17 = 11101
We can solve this problem using BFS, every node of implicit graph will be a binary digit
number and if number is x, then its next level node will be x0 and x1 (x concatenated with
0 and 1).
In starting we will push 1 into our queue, which will push 10 and 11 into queue later and
so on, after taking number from queue we’ll check whether this number is multiple of given
number or not, if yes then return this number as result, this will be our final result because
BFS proceeds level by level so first answer we got will be our smallest answer also.
In below code binary digit number is treated as string, because for some number it can be
very large and can outside the limit of even long long, mod operation on number stored as
string is also implemented.
1142
Chapter 159. Find the smallest binary digit multiple of given number
Main optimization tweak of code is using a set for modular value, if a string with same mod
value is previously occurred we won’t push this new string into our queue. Reason for not
pushing new string is explained below,
Let x and y be strings, which gives same modular value. Let x be the smaller one. let z be
another string which when appended to y gives us a number divisible by N. If so, then we
can also append this string to x, which is smaller than y, and still get a number divisible by
n. So we can safely ignore y, as the smallest result will be obtained via x only.
C++
1143
Chapter 159. Find the smallest binary digit multiple of given number
string t = "1";
// In starting push 1 into our queue
q.push(t);
// loop untill queue is not empty
while (!q.empty())
{
// Take the front number from queue.
t = q.front(); q.pop();
// Find remainder of t with respect to N.
int rem = mod(t, N);
// if remainder is 0 then we have
// found our solution
if (rem == 0)
return t;
// If this remainder is not previously seen,
// then push t0 and t1 in our queue
else if(visit.find(rem) == visit.end())
{
visit.insert(rem);
q.push(t + "0");
q.push(t + "1");
}
}
}
// Driver code to test above methods
int main()
{
int N = 12;
cout << getMinimumMultipleOfBinaryDigit(N);
return 0;
}
Python3
1144
Chapter 159. Find the smallest binary digit multiple of given number
# s = str(A)
# print(s)
# print(A)
result = A * i
# method returns smallest
# multiple which has
# binary digits
allowed_chars = set('01')
validationString = str(result)
if set(validationString).issubset(allowed_chars):
flag = True;
break;
else:
i = i + 1
return validationString
# Driver code
n = 12
print(multiple(n))
# This code is contributed
# by HARDY_123
Output:
11100
Improved By : HARDY_123
Source
https://www.geeksforgeeks.org/find-the-smallest-binary-digit-multiple-of-given-number/
1145
Chapter 160
Input : M[3][3] = {{ 0 , 3 , 2 },
{ 3 , 3 , 0 },
{ 1 , 3 , 0 }};
Output : Yes
Input : M[4][4] = {{ 0 , 3 , 1 , 0 },
{ 3 , 0 , 3 , 3 },
{ 2 , 3 , 0 , 3 },
{ 0 , 3 , 3 , 3 }};
Output : Yes
1146
Chapter 160. Find whether there is path between two cells in matrix
return false ;
1147
Chapter 160. Find whether there is path between two cells in matrix
class Graph
{
int V ;
list < int > *adj;
public :
Graph( int V )
{
this->V = V ;
adj = new list<int>[V];
}
void addEdge( int s , int d ) ;
bool BFS ( int s , int d) ;
};
// add edge to graph
void Graph :: addEdge ( int s , int d )
{
adj[s].push_back(d);
adj[d].push_back(s);
}
// BFS function to find path from source to sink
bool Graph :: BFS(int s, int d)
{
// Base case
if (s == d)
return true;
// Mark all the vertices as not visited
bool *visited = new bool[V];
for (int i = 0; i < V; i++)
visited[i] = false;
// Create a queue for BFS
list<int> queue;
// Mark the current node as visited and
// enqueue it
visited[s] = true;
queue.push_back(s);
// it will be used to get all adjacent
// vertices of a vertex
list<int>::iterator i;
while (!queue.empty())
{
// Dequeue a vertex from queue
1148
Chapter 160. Find whether there is path between two cells in matrix
s = queue.front();
queue.pop_front();
// Get all adjacent vertices of the
// dequeued vertex s. If a adjacent has
// not been visited, then mark it visited
// and enqueue it
for (i = adj[s].begin(); i != adj[s].end(); ++i)
{
// If this adjacent node is the destination
// node, then return true
if (*i == d)
return true;
// Else, continue to do BFS
if (!visited[*i])
{
visited[*i] = true;
queue.push_back(*i);
}
}
}
// If BFS is complete without visiting d
return false;
}
bool isSafe(int i, int j, int M[][N])
{
if ((i < 0 || i >= N) ||
(j < 0 || j >= N ) || M[i][j] == 0)
return false;
return true;
}
// Returns true if there is a path from a source (a
// cell with value 1) to a destination (a cell with
// value 2)
bool findPath(int M[][N])
{
int s , d ; // source and destination
int V = N*N+2;
Graph g(V);
// create graph with n*n node
// each cell consider as node
int k = 1 ; // Number of current vertex
for (int i =0 ; i < N ; i++)
1149
Chapter 160. Find whether there is path between two cells in matrix
{
for (int j = 0 ; j < N; j++)
{
if (M[i][j] != 0)
{
// connect all 4 adjacent cell to
// current cell
if ( isSafe ( i , j+1 , M ) )
g.addEdge ( k , k+1 );
if ( isSafe ( i , j-1 , M ) )
g.addEdge ( k , k-1 );
if (j< N-1 && isSafe ( i+1 , j , M ) )
g.addEdge ( k , k+N );
if ( i > 0 && isSafe ( i-1 , j , M ) )
g.addEdge ( k , k-N );
}
// source index
if( M[i][j] == 1 )
s = k ;
// destination index
if (M[i][j] == 2)
d = k;
k++;
}
}
// find path Using BFS
return g.BFS (s, d) ;
}
// driver program to check above function
int main()
{
int M[N][N] = {{ 0 , 3 , 0 , 1 },
{ 3 , 0 , 3 , 3 },
{ 2 , 3 , 3 , 3 },
{ 0 , 3 , 3 , 3 }
};
(findPath(M) == true) ?
cout << "Yes" : cout << "No" <<endl ;
return 0;
}
Output:
1150
Chapter 160. Find whether there is path between two cells in matrix
Yes
Source
https://www.geeksforgeeks.org/find-whether-path-two-cells-matrix/
1151
Chapter 161
Finding minimum vertex cover size of a graph using binary search - GeeksforGeeks
A vertex cover of an undirected graph is a subset of its vertices such that for every edge
(u, v) of the graph, either ‘u’ or ‘v’ is in vertex cover. There may be a lot of vertex covers
possible for a graph.
Problem Find the size of the minimum size vertex cover, that is, cardinality of a vertex
cover with minimum cardinality, for an undirected connected graph with V vertices and m
edges.
Examples:
Input: V = 6, E = 6
6
/
/
1 -----5
/|\
3 | \
\ | \
2 4
Output: Minimum vertex cover size = 2
Consider subset of vertices {1, 2}, every edge
in above graph is either incident on vertex 1
or 2. Hence the minimum vertex cover = {1, 2},
the size of which is 2.
1152
Chapter 161. Finding minimum vertex cover size of a graph using binary search
Input: V = 6, E = 7
2 ---- 4 ---- 6
/| |
1 | |
\| |
3 ---- 5
Output: Minimum vertex cover size = 3
Consider subset of vertices {2, 3, 4}, every
edge in above graph is either incident on
vertex 2, 3 or 4. Hence the minimum size of
a vertex cover can be 3.
Method 1 (Naive)
We can check in O(E + V) time if a given subset of vertices is a vertex cover or not, using
the following algorithm.
1 2 3 . . . k . . . n
0 0 0 . . . 1 . . . 1
1153
Chapter 161. Finding minimum vertex cover size of a graph using binary search
The array is sorted and hence binary searchable, as no index before k will have a ‘1’, and
every index after k(inclusive) will have a ‘1’, so k is the answer.
So we can apply Binary Search to find the minimum size vertex set that covers all edges (this
problem is equivalent to finding last 1 in isCover[]). Now the problem is how to generate all
subsets of a given size. The idea is to use Gosper’s hack.
What is Gosper’s Hack?
Gosper’s hack is a technique to get the next number with same number of bits set. So we
set the first x bits from right and generate next number with x bits set until the number is
less than 2V . In this way, we can generate all V Cx numbers with x bits set.
Source : StackExchange
We use gosper’s hack to generate all subsets of size x(0 < x <= V), that is, to check whether
we have a ’1’ or ’0’ at any index x in isCover[] array.
1154
Chapter 161. Finding minimum vertex cover size of a graph using binary search
1155
Chapter 161. Finding minimum vertex cover size of a graph using binary search
// Returns answer to graph stored in gr[][]
int findMinCover(int n, int m)
{
// Binary search the answer
int left = 1, right = n;
while (right > left)
{
int mid = (left + right) >> 1;
if (isCover(n, mid, m) == false)
left = mid + 1;
else
right = mid;
}
// at the end of while loop both left and
// right will be equal,/ as when they are
// not, the while loop won't exit the minimum
// size vertex cover = left = right
return left;
}
// Inserts an edge in the graph
void insertEdge(int u, int v)
{
gr[u][v] = 1;
gr[v][u] = 1; // Undirected graph
}
// Driver code
int main()
{
/*
6
/
1 ----- 5 vertex cover = {1, 2}
/|\
3 | \
\ | \
2 4 */
int V = 6, E = 6;
insertEdge(1, 2);
insertEdge(2, 3);
insertEdge(1, 3);
insertEdge(1, 4);
insertEdge(1, 5);
insertEdge(1, 6);
cout << "Minimum size of a vertex cover = "
1156
Chapter 161. Finding minimum vertex cover size of a graph using binary search
Output:
Conclusion:
V V V V
Time Complexity : O (E * ( CV/2 + CV/4 + CV/8 +…upto Ck ) )
Source
https://www.geeksforgeeks.org/finding-minimum-vertex-cover-graph-using-binary-search/
1157
Chapter 162
Input:
screen[M][N] = {{1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 0, 0},
{1, 0, 0, 1, 1, 0, 1, 1},
{1, 2, 2, 2, 2, 0, 1, 0},
{1, 1, 1, 2, 2, 0, 1, 0},
{1, 1, 1, 2, 2, 2, 2, 0},
{1, 1, 1, 1, 1, 2, 1, 1},
{1, 1, 1, 1, 1, 2, 2, 1},
};
x = 4, y = 4, newColor = 3
The values in the given 2D screen indicate colors of the pixels.
x and y are coordinates of the brush, newColor is the color that
should replace the previous color on screen[x][y] and all surrounding
pixels with same color.
Output:
Screen should be changed to following.
screen[M][N] = {{1, 1, 1, 1, 1, 1, 1, 1},
1158
Chapter 162. Flood fill Algorithm - how to implement fill() in paint?
{1, 1, 1, 1, 1, 1, 0, 0},
{1, 0, 0, 1, 1, 0, 1, 1},
{1, 3, 3, 3, 3, 0, 1, 0},
{1, 1, 1, 3, 3, 0, 1, 0},
{1, 1, 1, 3, 3, 3, 3, 0},
{1, 1, 1, 1, 1, 3, 1, 1},
{1, 1, 1, 1, 1, 3, 3, 1},
};
1159
Chapter 162. Flood fill Algorithm - how to implement fill() in paint?
// Recur for north, east, south and west
floodFillUtil(screen, x+1, y, prevC, newC);
floodFillUtil(screen, x-1, y, prevC, newC);
floodFillUtil(screen, x, y+1, prevC, newC);
floodFillUtil(screen, x, y-1, prevC, newC);
}
// It mainly finds the previous color on (x, y) and
// calls floodFillUtil()
void floodFill(int screen[][N], int x, int y, int newC)
{
int prevC = screen[x][y];
floodFillUtil(screen, x, y, prevC, newC);
}
// Driver program to test above function
int main()
{
int screen[M][N] = {{1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 0, 0},
{1, 0, 0, 1, 1, 0, 1, 1},
{1, 2, 2, 2, 2, 0, 1, 0},
{1, 1, 1, 2, 2, 0, 1, 0},
{1, 1, 1, 2, 2, 2, 2, 0},
{1, 1, 1, 1, 1, 2, 1, 1},
{1, 1, 1, 1, 1, 2, 2, 1},
};
int x = 4, y = 4, newC = 3;
floodFill(screen, x, y, newC);
cout << "Updated screen after call to floodFill: n";
for (int i=0; i<M; i++)
{
for (int j=0; j<N; j++)
cout << screen[i][j] << " ";
cout << endl;
}
}
Output:
1160
Chapter 162. Flood fill Algorithm - how to implement fill() in paint?
1 1 1 3 3 3 3 0
1 1 1 1 1 3 1 1
1 1 1 1 1 3 3 1
References:
http://en.wikipedia.org/wiki/Flood_fill
This article is contributed by Anmol. Please write comments if you find anything incorrect,
or you want to share more information about the topic discussed above.
Source
https://www.geeksforgeeks.org/flood-fill-algorithm-implement-fill-paint/
1161
Chapter 163
Input:
graph[][] = { {0, 5, INF, 10},
{INF, 0, 3, INF},
{INF, INF, 0, 1},
{INF, INF, INF, 0} }
which represents the following graph
10
(0)------->(3)
| /|\
5 | |
| | 1
\|/ |
(1)------->(2)
3
Note that the value of graph[i][j] is 0 if i is equal to j
And graph[i][j] is INF (infinite) if there is no edge from vertex i to j.
Output:
Shortest distance matrix
0 5 8 9
INF 0 3 4
1162
Chapter 163. Floyd Warshall Algorithm DP-16
INF INF 0 1
INF INF INF 0
1163
Chapter 163. Floyd Warshall Algorithm DP-16
we can say the initial values of shortest distances are based
on shortest paths considering no intermediate vertex. */
for (i = 0; i < V; i++)
for (j = 0; j < V; j++)
dist[i][j] = graph[i][j];
/* Add all vertices one by one to the set of intermediate vertices.
---> Before start of an iteration, we have shortest distances between all
pairs of vertices such that the shortest distances consider only the
vertices in set {0, 1, 2, .. k-1} as intermediate vertices.
----> After the end of an iteration, vertex no. k is added to the set of
intermediate vertices and the set becomes {0, 1, 2, .. k} */
for (k = 0; k < V; k++)
{
// Pick all vertices as source one by one
for (i = 0; i < V; i++)
{
// Pick all vertices as destination for the
// above picked source
for (j = 0; j < V; j++)
{
// If vertex k is on the shortest path from
// i to j, then update the value of dist[i][j]
if (dist[i][k] + dist[k][j] < dist[i][j])
dist[i][j] = dist[i][k] + dist[k][j];
}
}
}
// Print the shortest distance matrix
printSolution(dist);
}
/* A utility function to print solution */
void printSolution(int dist[][V])
{
printf ("The following matrix shows the shortest distances"
" between every pair of vertices \n");
for (int i = 0; i < V; i++)
{
for (int j = 0; j < V; j++)
{
if (dist[i][j] == INF)
printf("%7s", "INF");
else
printf ("%7d", dist[i][j]);
}
printf("\n");
1164
Chapter 163. Floyd Warshall Algorithm DP-16
}
}
// driver program to test above function
int main()
{
/* Let us create the following weighted graph
10
(0)------->(3)
| /|\
5 | |
| | 1
\|/ |
(1)------->(2)
3 */
int graph[V][V] = { {0, 5, INF, 10},
{INF, 0, 3, INF},
{INF, INF, 0, 1},
{INF, INF, INF, 0}
};
// Print the solution
floydWarshall(graph);
return 0;
}
Java
1165
Chapter 163. Floyd Warshall Algorithm DP-16
1166
Chapter 163. Floyd Warshall Algorithm DP-16
}
}
// Driver program to test above function
public static void main (String[] args)
{
/* Let us create the following weighted graph
10
(0)------->(3)
| /|\
5 | |
| | 1
\|/ |
(1)------->(2)
3 */
int graph[][] = { {0, 5, INF, 10},
{INF, 0, 3, INF},
{INF, INF, 0, 1},
{INF, INF, INF, 0}
};
AllPairShortestPath a = new AllPairShortestPath();
// Print the solution
a.floydWarshall(graph);
}
}
// Contributed by Aakash Hasija
Python
1167
Chapter 163. Floyd Warshall Algorithm DP-16
1168
Chapter 163. Floyd Warshall Algorithm DP-16
10
(0)------->(3)
| /|\
5 | |
| | 1
\|/ |
(1)------->(2)
3 """
graph = [[0,5,INF,10],
[INF,0,3,INF],
[INF, INF, 0, 1],
[INF, INF, INF, 0]
]
# Print the solution
floydWarshall(graph);
# This code is contributed by Nikhil Kumar Singh(nickzuck_007)
C#
1169
Chapter 163. Floyd Warshall Algorithm DP-16
1170
Chapter 163. Floyd Warshall Algorithm DP-16
Output:
Following matrix shows the shortest distances between every pair of vertices
0 5 8 9
INF 0 3 4
INF INF 0 1
INF INF INF 0
1171
Chapter 163. Floyd Warshall Algorithm DP-16
The above program only prints the shortest distances. We can modify the solution to print
the shortest paths also by storing the predecessor information in a separate 2D matrix.
Also, the value of INF can be taken as INT_MAX from limits.h to make sure that we
handle maximum possible value. When we take INF as INT_MAX, we need to change the
if condition in the above program to avoid arithmetic overflow.
#include
Source
https://www.geeksforgeeks.org/floyd-warshall-algorithm-dp-16/
1172
Chapter 164
a -> c
b -> c
b -> e
c -> a
c -> b
c -> d
c -> e
d -> c
e -> c
e -> b
It can be represented by the following Python data structure. This is a dictionary whose
keys are the nodes of the graph. For each key, the corresponding value is a list containing
the nodes that are connected by a direct arc from this node.
1173
Chapter 164. Generate a graph using Dictionary in Python
defaultdict: Usually, a Python dictionary throws a KeyError if you try to get an item with
a key that is not currently in the dictionary. defaultdict allows that if a key is not found in
the dictionary, then instead of a KeyError being thrown, a new entry is created. The type
of this new entry is given by the argument of defaultdict.
Python Function to generate graph:
# definition of function
def generate_edges(graph):
edges = []
1174
Chapter 164. Generate a graph using Dictionary in Python
return edges
Output:
[('a', 'c'), ('c', 'd'), ('c', 'e'), ('c', 'a'), ('c', 'b'),
('b', 'c'), ('b', 'e'), ('e', 'b'), ('e', 'c'), ('d', 'c')]
1175
Chapter 164. Generate a graph using Dictionary in Python
As we have taken example of undirected graph, so we have print same edge twice say as
(‘a’,’c’) and (‘c’,’a’). We can overcome this with use of directed graph.
Below are some more programs on graphs in python:
Output:
2. Program to generate all the possible paths from one node to the other.:
In the above discussed program, we generated the first possible path. Now, let us gen-
erate all the possible paths from the start node to the end node. The basic functioning
works same as the functioning of the above code. The place where the difference comes
1176
Chapter 164. Generate a graph using Dictionary in Python
is instead of instantly returning the first path, it saves that path in a list named as
‘paths’ in the example given below. Finally, after iterating over all the possible ways,
it returns the list of paths. If there is no path from the starting node to the ending
node, it returns None.
Output:
1177
Chapter 164. Generate a graph using Dictionary in Python
'a':['c'],
'b':['d'],
'c':['e'],
'd':['a', 'd'],
'e':['b', 'c']
}
# function to find the shortest path
def find_shortest_path(graph, start, end, path =[]):
path = path + [start]
if start == end:
return path
shortest = None
for node in graph[start]:
if node not in path:
newpath = find_shortest_path(graph, node, end, path)
if newpath:
if not shortest or len(newpath) < len(shortest):
shortest = newpath
return shortest
# Driver function call to print
# the shortest path
print(find_shortest_path(graph, 'd', 'c'))
Output:
Source
https://www.geeksforgeeks.org/generate-graph-using-dictionary-python/
1178
Chapter 165
Given a matrix of ‘O’ and ‘X’, replace ’O’ with ’X’ if surrounded by ’X’ - GeeksforGeeks
Given a matrix where every element is either ‘O’ or ‘X’, replace ‘O’ with ‘X’ if surrounded
by ‘X’. A ‘O’ (or a set of ‘O’) is considered to be by surrounded by ‘X’ if there are ‘X’ at
locations just below, just above, just left and just right of it.
Examples:
1179
Chapter 165. Given a matrix of ’O’ and ’X’, replace ’O’ with ’X’ if surrounded by ’X’
This is mainly an application of Flood-Fill algorithm. The main difference here is that a
‘O’ is not replaced by ‘X’ if it lies in region that ends on a boundary. Following are simple
steps to do this special flood fill.
1) Traverse the given matrix and replace all ‘O’ with a special character ‘-‘.
2) Traverse four edges of given matrix and call floodFill(‘-‘, ‘O’) for every ‘-‘ on edges. The
remaining ‘-‘ are the characters that indicate ‘O’s (in the original matrix) to be replaced by
‘X’.
3) Traverse the matrix and replace all ‘-‘s with ‘X’s.
Let us see steps of above algorithm with an example. Let following be the
input matrix.
Step 2: Call floodFill(‘-‘, ‘O’) for all edge elements with value equals to ‘-‘
1180
Chapter 165. Given a matrix of ’O’ and ’X’, replace ’O’ with ’X’ if surrounded by ’X’
1181
Chapter 165. Given a matrix of ’O’ and ’X’, replace ’O’ with ’X’ if surrounded by ’X’
1182
Chapter 165. Given a matrix of ’O’ and ’X’, replace ’O’ with ’X’ if surrounded by ’X’
for (int i=0; i<M; i++)
{
for (int j=0; j<N; j++)
cout << mat[i][j] << " ";
cout << endl;
}
return 0;
}
Java
1183
Chapter 165. Given a matrix of ’O’ and ’X’, replace ’O’ with ’X’ if surrounded by ’X’
// Returns size of maximum
// size subsquare matrix
// surrounded by 'X'
static void replaceSurrounded(char mat[][])
{
// Step 1: Replace
// all 'O' with '-'
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
if (mat[i][j] == 'O')
mat[i][j] = '-';
// Call floodFill for
// all '-' lying on edges
for (int i = 0; i < M; i++) // Left side
if (mat[i][0] == '-')
floodFillUtil(mat, i, 0,
'-', 'O');
for (int i = 0; i < M; i++) // Right side
if (mat[i][N - 1] == '-')
floodFillUtil(mat, i, N - 1,
'-', 'O');
for (int i = 0; i < N; i++) // Top side
if (mat[0][i] == '-')
floodFillUtil(mat, 0, i,
'-', 'O');
for (int i = 0; i < N; i++) // Bottom side
if (mat[M - 1][i] == '-')
floodFillUtil(mat, M - 1,
i, '-', 'O');
// Step 3: Replace
// all '-' with 'X'
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
if (mat[i][j] == '-')
mat[i][j] = 'X';
}
// Driver Code
public static void main (String[] args)
{
char[][] mat = {{'X', 'O', 'X',
'O', 'X', 'X'},
{'X', 'O', 'X',
'X', 'O', 'X'},
1184
Chapter 165. Given a matrix of ’O’ and ’X’, replace ’O’ with ’X’ if surrounded by ’X’
C#
// A C# program to replace
// all 'O's with 'X''s if
// surrounded by 'X'
using System;
class GFG
{
static int M = 6;
static int N = 6;
static void floodFillUtil(char [,]mat, int x,
int y, char prevV,
char newV)
{
// Base cases
if (x < 0 || x >= M ||
y < 0 || y >= N)
return;
if (mat[x, y] != prevV)
return;
// Replace the color at (x, y)
1185
Chapter 165. Given a matrix of ’O’ and ’X’, replace ’O’ with ’X’ if surrounded by ’X’
mat[x, y] = newV;
// Recur for north,
// east, south and west
floodFillUtil(mat, x + 1, y,
prevV, newV);
floodFillUtil(mat, x - 1, y,
prevV, newV);
floodFillUtil(mat, x, y + 1,
prevV, newV);
floodFillUtil(mat, x, y - 1,
prevV, newV);
}
// Returns size of maximum
// size subsquare matrix
// surrounded by 'X'
static void replaceSurrounded(char [,]mat)
{
// Step 1: Replace
// all 'O' with '-'
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
if (mat[i, j] == 'O')
mat[i, j] = '-';
// Call floodFill for
// all '-' lying on edges
for (int i = 0; i < M; i++) // Left side
if (mat[i, 0] == '-')
floodFillUtil(mat, i, 0,
'-', 'O');
for (int i = 0; i < M; i++) // Right side
if (mat[i, N - 1] == '-')
floodFillUtil(mat, i, N - 1,
'-', 'O');
for (int i = 0; i < N; i++) // Top side
if (mat[0, i] == '-')
floodFillUtil(mat, 0, i,
'-', 'O');
for (int i = 0; i < N; i++) // Bottom side
if (mat[M - 1, i] == '-')
floodFillUtil(mat, M - 1,
i, '-', 'O');
// Step 3: Replace
// all '-' with 'X'
1186
Chapter 165. Given a matrix of ’O’ and ’X’, replace ’O’ with ’X’ if surrounded by ’X’
PHP
<?php
// A PHP program to replace all
// 'O's with 'X''s if surrounded by 'X'
// Size of given
// matrix is M X N
$M = 6;
$N = 6;
1187
Chapter 165. Given a matrix of ’O’ and ’X’, replace ’O’ with ’X’ if surrounded by ’X’
// A recursive function to replace
// previous value 'prevV' at '(x, y)'
// and all surrounding values of
// (x, y) with new value 'newV'.
function floodFillUtil(&$mat, $x, $y,
$prevV, $newV)
{
// Base cases
if ($x < 0 || $x >= $GLOBALS['M'] ||
$y < 0 || $y >= $GLOBALS['N'])
return;
if ($mat[$x][$y] != $prevV)
return;
// Replace the color at (x, y)
$mat[$x][$y] = $newV;
// Recur for north,
// east, south and west
floodFillUtil($mat, $x + 1, $y, $prevV, $newV);
floodFillUtil($mat, $x - 1, $y, $prevV, $newV);
floodFillUtil($mat, $x, $y + 1, $prevV, $newV);
floodFillUtil($mat, $x, $y - 1, $prevV, $newV);
}
// Returns size of maximum
// size subsquare matrix
// surrounded by 'X'
function replaceSurrounded(&$mat)
{
// Step 1: Replace all 'O' with '-'
for ($i = 0; $i < $GLOBALS['M']; $i++)
for ($j = 0; $j < $GLOBALS['N']; $j++)
if ($mat[$i][$j] == 'O')
$mat[$i][$j] = '-';
// Call floodFill for all
// '-' lying on edges
for ($i = 0;
$i < $GLOBALS['M']; $i++) // Left side
if ($mat[$i][0] == '-')
floodFillUtil($mat, $i, 0, '-', 'O');
for ($i = 0; $i < $GLOBALS['M']; $i++) // Right side
if ($mat[$i][$GLOBALS['N'] - 1] == '-')
1188
Chapter 165. Given a matrix of ’O’ and ’X’, replace ’O’ with ’X’ if surrounded by ’X’
floodFillUtil($mat, $i,
$GLOBALS['N'] - 1, '-', 'O');
for ($i = 0; $i < $GLOBALS['N']; $i++) // Top side
if ($mat[0][$i] == '-')
floodFillUtil($mat, 0, $i, '-', 'O');
for ($i = 0; $i < $GLOBALS['N']; $i++) // Bottom side
if ($mat[$GLOBALS['M'] - 1][$i] == '-')
floodFillUtil($mat, $GLOBALS['M'] - 1,
$i, '-', 'O');
// Step 3: Replace all '-' with 'X'
for ($i = 0; $i < $GLOBALS['M']; $i++)
for ($j = 0; $j < $GLOBALS['N']; $j++)
if ($mat[$i][$j] == '-')
$mat[$i][$j] = 'X';
}
// Driver Code
$mat = array(array('X', 'O', 'X', 'O', 'X', 'X'),
array('X', 'O', 'X', 'X', 'O', 'X'),
array('X', 'X', 'X', 'O', 'X', 'X'),
array('O', 'X', 'X', 'X', 'X', 'X'),
array('X', 'X', 'X', 'O', 'X', 'O'),
array('O', 'O', 'X', 'O', 'O', 'O'));
replaceSurrounded($mat);
for ($i = 0; $i < $GLOBALS['M']; $i++)
{
for ($j = 0; $j < $GLOBALS['N']; $j++)
echo $mat[$i][$j]." ";
echo "\n";
}
// This code is contributed by ChitraNayal
?>
Output:
X O X O X X
X O X X X X
X X X X X X
O X X X X X
X X X O X O
O O X O O O
1189
Chapter 165. Given a matrix of ’O’ and ’X’, replace ’O’ with ’X’ if surrounded by ’X’
Time Complexity of the above solution is O(MN). Note that every element of matrix is
processed at most three times.
This article is contributed by Anmol. Please write comments if you find anything incorrect,
or you want to share more information about the topic discussed above.
Improved By : shiv_bhakt, ChitraNayal
Source
https://www.geeksforgeeks.org/given-matrix-o-x-replace-o-x-surrounded-x/
1190
Chapter 166
1191
Chapter 166. Graph Coloring Set 1 (Introduction and Applications)
Source
https://www.geeksforgeeks.org/graph-coloring-applications/
1192
Chapter 167
Following are C++ and Java implementations of the above Greedy Algorithm.
C++
1193
Chapter 167. Graph Coloring Set 2 (Greedy Algorithm)
{
int V; // No. of vertices
list<int> *adj; // A dynamic array of adjacency lists
public:
// Constructor and destructor
Graph(int V) { this->V = V; adj = new list<int>[V]; }
~Graph() { delete [] adj; }
// function to add an edge to graph
void addEdge(int v, int w);
// Prints greedy coloring of the vertices
void greedyColoring();
};
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w);
adj[w].push_back(v); // Note: the graph is undirected
}
// Assigns colors (starting from 0) to all vertices and prints
// the assignment of colors
void Graph::greedyColoring()
{
int result[V];
// Assign the first color to first vertex
result[0] = 0;
// Initialize remaining V-1 vertices as unassigned
for (int u = 1; u < V; u++)
result[u] = -1; // no color is assigned to u
// A temporary array to store the available colors. True
// value of available[cr] would mean that the color cr is
// assigned to one of its adjacent vertices
bool available[V];
for (int cr = 0; cr < V; cr++)
available[cr] = false;
// Assign colors to remaining V-1 vertices
for (int u = 1; u < V; u++)
{
// Process all adjacent vertices and flag their colors
// as unavailable
list<int>::iterator i;
for (i = adj[u].begin(); i != adj[u].end(); ++i)
1194
Chapter 167. Graph Coloring Set 2 (Greedy Algorithm)
1195
Chapter 167. Graph Coloring Set 2 (Greedy Algorithm)
Java
1196
Chapter 167. Graph Coloring Set 2 (Greedy Algorithm)
// Assign colors to remaining V-1 vertices
for (int u = 1; u < V; u++)
{
// Process all adjacent vertices and flag their colors
// as unavailable
Iterator<Integer> it = adj[u].iterator() ;
while (it.hasNext())
{
int i = it.next();
if (result[i] != -1)
available[result[i]] = false;
}
// Find the first available color
int cr;
for (cr = 0; cr < V; cr++){
if (available[cr])
break;
}
result[u] = cr; // Assign the found color
// Reset the values back to true for the next iteration
Arrays.fill(available, true);
}
// print the result
for (int u = 0; u < V; u++)
System.out.println("Vertex " + u + " ---> Color "
+ result[u]);
}
// Driver method
public static void main(String args[])
{
Graph g1 = new Graph(5);
g1.addEdge(0, 1);
g1.addEdge(0, 2);
g1.addEdge(1, 2);
g1.addEdge(1, 3);
g1.addEdge(2, 3);
g1.addEdge(3, 4);
System.out.println("Coloring of graph 1");
g1.greedyColoring();
System.out.println();
Graph g2 = new Graph(5);
1197
Chapter 167. Graph Coloring Set 2 (Greedy Algorithm)
g2.addEdge(0, 1);
g2.addEdge(0, 2);
g2.addEdge(1, 2);
g2.addEdge(1, 4);
g2.addEdge(2, 4);
g2.addEdge(4, 3);
System.out.println("Coloring of graph 2 ");
g2.greedyColoring();
}
}
// This code is contributed by Aakash Hasija
Output:
Coloring of graph 1
Vertex 0 ---> Color 0
Vertex 1 ---> Color 1
Vertex 2 ---> Color 2
Vertex 3 ---> Color 0
Vertex 4 ---> Color 1
Coloring of graph 2
Vertex 0 ---> Color 0
Vertex 1 ---> Color 1
Vertex 2 ---> Color 2
Vertex 3 ---> Color 0
Vertex 4 ---> Color 3
1198
Chapter 167. Graph Coloring Set 2 (Greedy Algorithm)
So the order in which the vertices are picked is important. Many people have sug-
gested different ways to find an ordering that work better than the basic algorithm
on average. The most common is Welsh–Powell Algorithm which considers vertices in
descending order of degrees.
How does the basic algorithm guarantee an upper bound of d+1?
Here d is the maximum degree in the given graph. Since d is maximum degree, a vertex
cannot be attached to more than d vertices. When we color a vertex, at most d colors could
have already been used by its adjacent. To color this vertex, we need to pick the smallest
numbered color that is not used by the adjacent vertices. If colors are numbered like 1, 2,
…., then the value of such smallest number must be between 1 to d+1 (Note that d numbers
are already picked by adjacent vertices).
1199
Chapter 167. Graph Coloring Set 2 (Greedy Algorithm)
This can also be proved using induction. See thisvideo lecture for proof.
We will soon be discussing some interesting facts about chromatic number and graph color-
ing.
Improved By : ChamanJhinga
Source
https://www.geeksforgeeks.org/graph-coloring-set-2-greedy-algorithm/
1200
Chapter 168
Graph implementation using STL for competitive programming Set 1 (DFS of Unweighted
and Undirected) - GeeksforGeeks
We have introduced Graph basics in Graph and its representations. In this post, a different
STL based representation is used that can be helpful to quickly implement graph using
vectors. The implementation is for adjacency list representation of graph.
Following is an example undirected and unweighted graph with 5 vertices.
1201
Chapter 168. Graph implementation using STL for competitive programming Set 1 (DFS
of Unweighted and Undirected)
• vector : A sequence container. Here we use it to store adjacency lists of all vertices.
We use vertex number as index in this vector.
The idea is to to represent graph as an array of vectors such that every vector represents
adjacency list of a vertex. Below is complete STL based C++ program for DFS Traversal.
1202
Chapter 168. Graph implementation using STL for competitive programming Set 1 (DFS
of Unweighted and Undirected)
// unvisited vertices.
void DFS(vector<int> adj[], int V)
{
vector<bool> visited(V, false);
for (int u=0; u<V; u++)
if (visited[u] == false)
DFSUtil(u, adj, visited);
}
// Driver code
int main()
{
int V = 5;
// The below line may not work on all
// compilers. If it does not work on
// your compiler, please replace it with
// following
// vector<int> *adj = new vector<int>[V];
vector<int> adj[V];
// Vertex numbers should be from 0 to 4.
addEdge(adj, 0, 1);
addEdge(adj, 0, 4);
addEdge(adj, 1, 2);
addEdge(adj, 1, 3);
addEdge(adj, 1, 4);
addEdge(adj, 2, 3);
addEdge(adj, 3, 4);
DFS(adj, V);
return 0;
}
Output :
0 1 2 3 4
Source
https://www.geeksforgeeks.org/graph-implementation-using-stl-for-competitive-programming-set-1-dfs-of-unweight
1203
Chapter 169
Graph implementation using STL for competitive programming Set 2 (Weighted graph) -
GeeksforGeeks
In Set 1, unweighted graph is discussed. In this post, weighted graph representation using
STL is discussed. The implementation is for adjacency list representation of weighted graph.
1204
Chapter 169. Graph implementation using STL for competitive programming Set 2
(Weighted graph)
• vector : A sequence container. Here we use it to store adjacency lists of all vertices.
We use vertex number as index in this vector.
• pair : A simple container to store pair of elements. Here we use it to store adjacent
vertex number and weight of edge connecting to the adjacent.
The idea is to use a vector of pair vectors. Below code implements the same.
1205
Chapter 169. Graph implementation using STL for competitive programming Set 2
(Weighted graph)
addEdge(adj, 1, 3, 40);
addEdge(adj, 1, 4, 50);
addEdge(adj, 2, 3, 60);
addEdge(adj, 3, 4, 70);
printGraph(adj, V);
return 0;
}
Output:
Source
https://www.geeksforgeeks.org/graph-implementation-using-stl-for-competitive-programming-set-2-weighted-graph
1206
Chapter 170
1207
Chapter 170. Graph representations using set and hash
Below is the code for adjacency list representation of an undirected graph using sets:
1208
Chapter 170. Graph representations using set and hash
1209
Chapter 170. Graph representations using set and hash
Output:
Pros: Queries like whether there is an edge from vertex u to vertex v can be done in O(log
V).
Cons:
1210
Chapter 170. Graph representations using set and hash
1211
Chapter 170. Graph representations using set and hash
}
}
// Searches for a given edge in the graph
void searchEdge(Graph* graph, int src, int dest)
{
auto itr = graph->adjList[src].find(dest);
if (itr == graph->adjList[src].end())
cout << endl << "Edge from " << src
<< " to " << dest << " not found."
<< endl;
else
cout << endl << "Edge from " << src
<< " to " << dest << " found."
<< endl;
}
// Driver code
int main()
{
// Create the graph given in the above figure
int V = 5;
struct Graph* graph = createGraph(V);
addEdge(graph, 0, 1);
addEdge(graph, 0, 4);
addEdge(graph, 1, 2);
addEdge(graph, 1, 3);
addEdge(graph, 1, 4);
addEdge(graph, 2, 3);
addEdge(graph, 3, 4);
// Print the adjacency list representation of
// the above graph
printGraph(graph);
// Search the given edge in the graph
searchEdge(graph, 2, 1);
searchEdge(graph, 0, 3);
return 0;
}
Output :
1212
Chapter 170. Graph representations using set and hash
Pros:
• Queries like whether there is an edge from vertex u to vertex v can be done in O(1).
Cons:
Note : adjacency matrix representation is the most optimized for edge search, but
space requirements of adjacency matrix are comparatively high for big sparse graphs. More-
over adjacency matrix has other disadvantages as well like BFS and DFS become costly as
we can’t quickly get all adjacent of a node.
Source
https://www.geeksforgeeks.org/graph-representations-using-set-hash/
1213
Chapter 171
Hamiltonian Cycle
Backtracking-6
(0)--(1)--(2)
| / \ |
| / \ |
| / \ |
(3)-------(4)
1214
Chapter 171. Hamiltonian Cycle Backtracking-6
(0)--(1)--(2)
| / \ |
| / \ |
| / \ |
(3) (4)
Naive Algorithm
Generate all possible configurations of vertices and print a configuration that satisfies the
given constraints. There will be n! (n factorial) configurations.
Backtracking Algorithm
Create an empty path array and add vertex 0 to it. Add other vertices, starting from the
vertex 1. Before adding a vertex, check for whether it is adjacent to the previously added
vertex and not already added. If we find such a vertex, we add the vertex as part of the
solution. If we do not find a vertex then we return false.
Implementation of Backtracking solution
Following are implementations of the Backtracking solution.
C/C++
1215
Chapter 171. Hamiltonian Cycle Backtracking-6
1216
Chapter 171. Hamiltonian Cycle Backtracking-6
1217
Chapter 171. Hamiltonian Cycle Backtracking-6
| / \ |
| / \ |
(3)-------(4) */
bool graph1[V][V] = {{0, 1, 0, 1, 0},
{1, 0, 1, 1, 1},
{0, 1, 0, 0, 1},
{1, 1, 0, 0, 1},
{0, 1, 1, 1, 0},
};
// Print the solution
hamCycle(graph1);
/* Let us create the following graph
(0)--(1)--(2)
| / \ |
| / \ |
| / \ |
(3) (4) */
bool graph2[V][V] = {{0, 1, 0, 1, 0},
{1, 0, 1, 1, 1},
{0, 1, 0, 0, 1},
{1, 1, 0, 0, 0},
{0, 1, 1, 0, 0},
};
// Print the solution
hamCycle(graph2);
return 0;
}
Java
1218
Chapter 171. Hamiltonian Cycle Backtracking-6
1219
Chapter 171. Hamiltonian Cycle Backtracking-6
}
/* If no vertex can be added to Hamiltonian Cycle
constructed so far, then return false */
return false;
}
/* This function solves the Hamiltonian Cycle problem using
Backtracking. It mainly uses hamCycleUtil() to solve the
problem. It returns false if there is no Hamiltonian Cycle
possible, otherwise return true and prints the path.
Please note that there may be more than one solutions,
this function prints one of the feasible solutions. */
int hamCycle(int graph[][])
{
path = new int[V];
for (int i = 0; i < V; i++)
path[i] = -1;
/* Let us put vertex 0 as the first vertex in the path.
If there is a Hamiltonian Cycle, then the path can be
started from any point of the cycle as the graph is
undirected */
path[0] = 0;
if (hamCycleUtil(graph, path, 1) == false)
{
System.out.println("\nSolution does not exist");
return 0;
}
printSolution(path);
return 1;
}
/* A utility function to print solution */
void printSolution(int path[])
{
System.out.println("Solution Exists: Following" +
" is one Hamiltonian Cycle");
for (int i = 0; i < V; i++)
System.out.print(" " + path[i] + " ");
// Let us print the first vertex again to show the
// complete cycle
System.out.println(" " + path[0] + " ");
}
// driver program to test above function
1220
Chapter 171. Hamiltonian Cycle Backtracking-6
Python
1221
Chapter 171. Hamiltonian Cycle Backtracking-6
self.V = vertices
''' Check if this vertex is an adjacent vertex
of the previously added vertex and is not
included in the path earlier '''
def isSafe(self, v, pos, path):
# Check if current vertex and last vertex
# in path are adjacent
if self.graph[ path[pos-1] ][v] == 0:
return False
# Check if current vertex not already in path
for vertex in path:
if vertex == v:
return False
return True
# A recursive utility function to solve
# hamiltonian cycle problem
def hamCycleUtil(self, path, pos):
# base case: if all vertices are
# included in the path
if pos == self.V:
# Last vertex must be adjacent to the
# first vertex in path to make a cyle
if self.graph[ path[pos-1] ][ path[0] ] == 1:
return True
else:
return False
# Try different vertices as a next candidate
# in Hamiltonian Cycle. We don't try for 0 as
# we included 0 as starting point in in hamCycle()
for v in range(1,self.V):
if self.isSafe(v, pos, path) == True:
path[pos] = v
if self.hamCycleUtil(path, pos+1) == True:
return True
# Remove current vertex if it doesn't
# lead to a solution
path[pos] = -1
1222
Chapter 171. Hamiltonian Cycle Backtracking-6
return False
def hamCycle(self):
path = [-1] * self.V
''' Let us put vertex 0 as the first vertex
in the path. If there is a Hamiltonian Cycle,
then the path can be started from any point
of the cycle as the graph is undirected '''
path[0] = 0
if self.hamCycleUtil(path,1) == False:
print "Solution does not exist\n"
return False
self.printSolution(path)
return True
def printSolution(self, path):
print "Solution Exists: Following is one Hamiltonian Cycle"
for vertex in path:
print vertex,
print path[0], "\n"
# Driver Code
''' Let us create the following graph
(0)--(1)--(2)
| / \ |
| / \ |
| / \ |
(3)-------(4) '''
g1 = Graph(5)
g1.graph = [ [0, 1, 0, 1, 0], [1, 0, 1, 1, 1],
[0, 1, 0, 0, 1,],[1, 1, 0, 0, 1],
[0, 1, 1, 1, 0], ]
# Print the solution
g1.hamCycle();
''' Let us create the following graph
(0)--(1)--(2)
| / \ |
| / \ |
| / \ |
(3) (4) '''
g2 = Graph(5)
g2.graph = [ [0, 1, 0, 1, 0], [1, 0, 1, 1, 1],
1223
Chapter 171. Hamiltonian Cycle Backtracking-6
Output:
Note that the above code always prints cycle starting from 0. Starting point should not
matter as cycle can be started from any point. If you want to change the starting point,
you should make two changes to above code.
Change “path[0] = 0;” to “path[0] = s;” where s is your new starting point. Also change
loop “for (int v = 1; v < V; v++)” in hamCycleUtil() to ”for (int v = 0; v < V; v++)”.
Please write comments if you find anything incorrect, or you want to share more information
about the topic discussed above.
Source
https://www.geeksforgeeks.org/hamiltonian-cycle-backtracking-6/
1224
Chapter 172
Here, generic tree is sometimes also called as N-ary tree or N-way tree where N denotes
the maximum number of child a node can have. In this problem array represents n number
of nodes in the tree.
Approach 1:
One solution is to traverse up the tree from node till root node is reached with node value
-1. While Traversing for each node store maximum path length.
Time Complexity of this solution is O(n^2).
Approach 2:
Build graph for N-ary Tree in O(n) time and apply BFS on the stored graph in O(n) time
and while doing BFS store maximum reached level. This solution does two iterations to
find the height of N-ary tree.
1225
Chapter 172. Height of a generic tree from parent array
#include <bits/stdc++.h>
#define MAX 1001
using namespace std;
// Adjacency list to
// store N-ary tree
vector<int> adj[MAX];
// Build tree in tree in O(n)
int build_tree(int arr[], int n)
{
int root_index = 0;
// Iterate for all nodes
for (int i = 0; i < n; i++) {
// if root node, store index
if (arr[i] == -1)
root_index = i;
else {
adj[i].push_back(arr[i]);
adj[arr[i]].push_back(i);
}
}
return root_index;
}
// Applying BFS
int BFS(int start)
{
// map is used as visited array
map<int, int> vis;
queue<pair<int, int> > q;
int max_level_reached = 0;
// height of root node is zero
q.push({ start, 0 });
// p.first denotes node in adjacency list
// p.second denotes level of p.first
pair<int, int> p;
while (!q.empty()) {
p = q.front();
vis[p.first] = 1;
1226
Chapter 172. Height of a generic tree from parent array
// store the maximum level reached
max_level_reached = max(max_level_reached,
p.second);
q.pop();
for (int i = 0; i < adj[p.first].size(); i++)
// adding 1 to previous level
// stored on node p.first
// which is parent of node adj[p.first][i]
// if adj[p.first][i] is not visited
if (!vis[adj[p.first][i]])
q.push({ adj[p.first][i], p.second + 1 });
}
return max_level_reached;
}
// Driver Function
int main()
{
// node 0 to node n-1
int parent[] = { -1, 0, 1, 2, 3 };
// Number of nodes in tree
int n = sizeof(parent) / sizeof(parent[0]);
int root_index = build_tree(parent, n);
int ma = BFS(root_index);
cout << "Height of N-ary Tree=" << ma;
return 0;
}
Output:
Time Complexity of this solution is O(2n) which converges to O(n) for very large n.
Approach 3:
We can find the height of N-ary Tree in only one iteration. We visit nodes from 0 to n-
1 iteratively and mark the unvisited ancestors recursively if they are not visited before till
we reach a node which is visited or we reach root node. If we reach visited node while
1227
Chapter 172. Height of a generic tree from parent array
traversing up the tree using parent links, then we use its height and will not go further in
recursion.
Explanation For Example 1::
1228
Chapter 172. Height of a generic tree from parent array
1229
Chapter 172. Height of a generic tree from parent array
// store maximum height so far
ma = max(ma, height[i]);
}
return ma;
}
// Driver Function
int main()
{
int parent[] = { -1, 0, 0, 0, 3, 1, 1, 2 };
int n = sizeof(parent) / sizeof(parent[0]);
cout << "Height of N-ary Tree = "
<< findHeight(parent, n);
return 0;
}
Output:
Source
https://www.geeksforgeeks.org/height-generic-tree-parent-array/
1230
Chapter 173
We have discussed the problem of finding out whether a given graph is Eulerian or not. In
this post, an algorithm to print Eulerian trail or circuit is discussed. The same problem can
be solved using Fleury’s Algorithm, however its complexity is O(E*E). Using Heirholzer’s
Algorithm, we can find the circuit/path in O(E), i.e., linear time.
Below is the Algorithm: ref (wiki ). Remember that a directed graph has an Eulerian cycle if
following conditions are true (1) All vertices with nonzero degree belong to a single strongly
connected component. (2) In degree and out degree of every vertex is same. The algorithm
assumes that the given graph has Eulerian Circuit.
1231
Chapter 173. Hierholzer’s Algorithm for directed graph
• Choose any starting vertex v, and follow a trail of edges from that vertex until return-
ing to v. It is not possible to get stuck at any vertex other than v, because indegree
and outdegree of every vertex must be same, when the trail enters another vertex w
there must be an unused edge leaving w.
The tour formed in this way is a closed tour, but may not cover all the vertices and
edges of the initial graph.
• As long as there exists a vertex u that belongs to the current tour but that has
adjacent edges not part of the tour, start another trail from u, following unused edges
until returning to u, and join the tour formed in this way to the previous tour.
Thus the idea is to keep following unused edges and removing them until we get stuck. Once
we get stuck, we back-track to the nearest vertex in our current path that has unused edges,
and we repeat the process until all the edges have been used. We can use another container
to maintain the final path.
Let’s take an example:
1232
Chapter 173. Hierholzer’s Algorithm for directed graph
1233
Chapter 173. Hierholzer’s Algorithm for directed graph
1234
Chapter 173. Hierholzer’s Algorithm for directed graph
adj2[0].push_back(1);
adj2[0].push_back(6);
adj2[1].push_back(2);
adj2[2].push_back(0);
adj2[2].push_back(3);
adj2[3].push_back(4);
adj2[4].push_back(2);
adj2[4].push_back(5);
adj2[5].push_back(0);
adj2[6].push_back(4);
printCircuit(adj2);
return 0;
}
Output:
Source
https://www.geeksforgeeks.org/hierholzers-algorithm-directed-graph/
1235
Chapter 174
1236
Chapter 174. Hopcroft-Karp Algorithm for Maximum Matching Set 1 (Introduction)
In the initial graph all single edges are augmenting paths and we can pick in any order. In
the middle stage, there is only one augmenting path. We remove matching edges of this
path from M and add not-matching edges. In final matching, there are no augmenting paths
so the matching is maximum.
Implementation of Hopcroft Karp algorithm is discussed in set 2.
Hopcroft–Karp Algorithm for Maximum Matching Set 2 (Implementation)
References:
https://en.wikipedia.org/wiki/Hopcroft%E2%80%93Karp_algorithm
http://www.dis.uniroma1.it/~leon/tcs/lecture2.pdf
1237
Chapter 174. Hopcroft-Karp Algorithm for Maximum Matching Set 1 (Introduction)
Source
https://www.geeksforgeeks.org/hopcroft-karp-algorithm-for-maximum-matching-set-1-introduction/
1238
Chapter 175
The question: where would you send each of your salespeople in order to minimize fair?
Possible assignment: Cost = 11000 INR
1239
Chapter 175. Hungarian Algorithm for Assignment Problem Set 1 (Introduction)
Other Possible assignment: Cost = 9500 INR and this is the best of the 3! possible
assignments.
1. For each row of the matrix, find the smallest element and subtract it from every
element in its row.
2. Do the same (as step 1) for all columns.
3. Cover all zeros in the matrix using minimum number of horizontal and vertical lines.
4. Test for Optimality: If the minimum number of covering lines is n, an optimal assign-
ment is possible and we are finished. Else if lines are lesser than n, we haven’t found
the optimal assignment, and must proceed to step 5.
5. Determine the smallest entry not covered by any line. Subtract this entry from each
uncovered row, and then add it to each covered column. Return to step 3.
1240
Chapter 175. Hungarian Algorithm for Assignment Problem Set 1 (Introduction)
0 1500 1000
500 2500 0
0 2000 500
0 0 1000
500 1000 0
0 500 500
cost matrix:
1500 4000 4500
2000 6000 3500
2000 4000 2500
1241
Chapter 175. Hungarian Algorithm for Assignment Problem Set 1 (Introduction)
0 2500 3000
0 4000 1500
0 2000 500
0 500 2500
0 2000 1000
0 0 0
In the next post, we will be discussing implementation of the above algorithm. The imple-
mentation requires more steps as we need to find minimum number of lines to cover all 0’s
using a program.
References:
1242
Chapter 175. Hungarian Algorithm for Assignment Problem Set 1 (Introduction)
http://www.math.harvard.edu/archive/20_spring_05/handouts/assignment_overheads.
pdf
https://www.youtube.com/watch?v=dQDZNHwuuOY
This article is contributed by Yash Varyani. Please write comments if you find anything
incorrect, or you want to share more information about the topic discussed above.
Source
https://www.geeksforgeeks.org/hungarian-algorithm-assignment-problem-set-1-introduction/
1243
Chapter 176
Hypercube Graph
Input : n = 3
Output : 8
Input : n = 2
Output : 4
In hypercube graph Q(n), n represents the degree of the graph. Hypercube graph represents
the maximum number of edges that can be connected to a graph to make it a n degree graph,
every vertex has same degree n and in that representation only a fixed number of edges and
vertices are added as shown in the figure below:
1244
Chapter 176. Hypercube Graph
All hypercube graphs are Hamiltonian, hypercube graph of order n has (2^n) vertices,
, for input n as order of graph we have to find the corresponding power of 2.
1245
Chapter 176. Hypercube Graph
// driver program
int main()
{
// n is the order of the graph
int n = 4;
cout << power(n);
return 0;
}
Output:
16
Source
https://www.geeksforgeeks.org/hypercube-graph/
1246
Chapter 177
Implementation of Graph in
JavaScript
• Adjacency Matrix
• Adjacency List
There are several other ways like incidence matrix, etc. but these two are most commonly
used. Refer to Graph and its representations for the explaination of Adjacency matrix and
list.
In this article, we would be using Adjacency List to represent a graph because in most
cases it has certain advantage over the other representation.
Now Lets see an example of Graph class-
1247
Chapter 177. Implementation of Graph in JavaScript
{
this.noOfVertices = noOfVertices;
this.AdjList = new Map();
}
// functions to be implemented
// addVertex(v)
// addEdge(v, w)
// printGraph()
// bfs(v)
// dfs(v)
}
The above example shows a framework of Graph class. We define two private variable
i.e noOfVertices to store the number of vertices in the graph and AdjList, which stores a
adjacency list of a particular vertex. We used a Map Object provided by ES6 in order to
implement Adjacency list. Where key of a map holds a vertex and values holds an array of
adjacent node.
Now lets implement functions to perform basic operations on graph:
1. addVertex(v) – It adds the vertex v as key to adjList and initialize its values with
an array.
1248
Chapter 177. Implementation of Graph in JavaScript
In order to add edge we get the adjacency list of the corresponding src vertex and add
the dest to the adjacency list.
1249
Chapter 177. Implementation of Graph in JavaScript
Now we will use the graph class to implement the graph shown above:
1250
Chapter 177. Implementation of Graph in JavaScript
g.printGraph();
Graph Traversal
We will implement the most common graph traversal algorithm:
1251
Chapter 177. Implementation of Graph in JavaScript
q.enqueue(neigh);
}
}
}
}
In the above method we have implemented the BFS algorithm. A Queue is used to
keep the unvisited nodes
Lets use the above method and traverse along the graph
// prints
// BFS
// A B D E C F
console.log("BFS");
g.bfs('A');
1252
Chapter 177. Implementation of Graph in JavaScript
}
// Recursive function which process and explore
// all the adjacent vertex of the vertex with which it is called
DFSUtil(vert, visited)
{
visited[vert] = true;
console.log(vert);
var get_neighbours = this.AdjList.get(vert);
for (var i in get_neighbours) {
var get_elem = get_neighbours[i];
if (!visited[get_elem])
this.DFSUtil(get_elem, visited);
}
}
In the above example dfs(startingNode) is used to initialize a visited array and DFSu-
til(vert, visited)
contains the implementation of DFS algorithm
Lets use the above method to traverse along the graph
// prints
// DFS
// A B C E D F
console.log("DFS");
g.dfs('A');
1253
Chapter 177. Implementation of Graph in JavaScript
Source
https://www.geeksforgeeks.org/implementation-graph-javascript/
1254
Chapter 178
Iterative Deepening
Search(IDS) or Iterative
Deepening Depth First
Search(IDDFS)
1. DFS first traverses nodes going through one adjacent of root, then next adjacent.
The problem with this approach is, if there is a node close to root, but not in first few
subtrees explored by DFS, then DFS reaches that node very late. Also, DFS may not
find shortest path to a node (in terms of number of edges).
2. BFS goes level by level, but requires more space. The space required by DFS is O(d)
where d is depth of tree, but space required by BFS is O(n) where n is number of
nodes in tree (Why? Note that the last level of tree can have around n/2 nodes and
second last level n/4 nodes and in BFS we need to have every level one by one in
queue).
IDDFS combines depth-first search’s space-efficiency and breadth-first search’s fast search
(for nodes closer to root).
How does IDDFS work?
IDDFS calls DFS for different depths starting from an initial value. In every call, DFS is
restricted from going beyond given depth. So basically we do DFS in a BFS fashion.
Algorithm:
1255
Chapter 178. Iterative Deepening Search(IDS) or Iterative Deepening Depth First
Search(IDDFS)
return false
An important thing to note is, we visit top level nodes multiple times. The last (or max
depth) level is visited once, second last level is visited twice, and so on. It may seem
expensive, but it turns out to be not so costly, since in a tree most of the nodes are in the
bottom level. So it does not matter much if the upper levels are visited multiple times.
Below is implementation of above algorithm
C/C++
1256
Chapter 178. Iterative Deepening Search(IDS) or Iterative Deepening Depth First
Search(IDDFS)
1257
Chapter 178. Iterative Deepening Search(IDS) or Iterative Deepening Depth First
Search(IDDFS)
return true;
return false;
}
// Driver code
int main()
{
// Let us create a Directed graph with 7 nodes
Graph g(7);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 3);
g.addEdge(1, 4);
g.addEdge(2, 5);
g.addEdge(2, 6);
int target = 6, maxDepth = 3, src = 0;
if (g.IDDFS(src, target, maxDepth) == true)
cout << "Target is reachable from source "
"within max depth";
else
cout << "Target is NOT reachable from source "
"within max depth";
return 0;
}
Python
1258
Chapter 178. Iterative Deepening Search(IDS) or Iterative Deepening Depth First
Search(IDDFS)
# A function to perform a Depth-Limited search
# from given source 'src'
def DLS(self,src,target,maxDepth):
if src == target : return True
# If reached the maximum depth, stop recursing.
if maxDepth <= 0 : return False
# Recur for all the vertices adjacent to this vertex
for i in self.graph[src]:
if(self.DLS(i,target,maxDepth-1)):
return True
return False
# IDDFS to search if target is reachable from v.
# It uses recursive DLS()
def IDDFS(self,src, target, maxDepth):
# Repeatedly depth-limit search till the
# maximum depth
for i in range(maxDepth):
if (self.DLS(src, target, i)):
return True
return False
# Create a graph given in the above diagram
g = Graph (7);
g.addEdge(0, 1)
g.addEdge(0, 2)
g.addEdge(1, 3)
g.addEdge(1, 4)
g.addEdge(2, 5)
g.addEdge(2, 6)
target = 6; maxDepth = 3; src = 0
if g.IDDFS(src, target, maxDepth) == True:
print ("Target is reachable from source " +
"within max depth")
else :
print ("Target is NOT reachable from source " +
"within max depth")
# This code is contributed by Neelam Pandey
Output :
1259
Chapter 178. Iterative Deepening Search(IDS) or Iterative Deepening Depth First
Search(IDDFS)
Illustration:
There can be two cases-
a) When the graph has no cycle: This case is simple. We can DFS multiple times with
different height limits.
b) When the graph has cycles. This is interesting as there is no visited flag in IDDFS.
Time Complexity: Suppose we have a tree having branching factor ‘b’ (number of children
of each node), and its depth ‘d’, i.e., there are bd nodes.
In an iterative deepening search, the nodes on the bottom level are expanded once, those
on the next to bottom level are expanded twice, and so on, up to the root of the search tree,
1260
Chapter 178. Iterative Deepening Search(IDS) or Iterative Deepening Depth First
Search(IDDFS)
which is expanded d+1 times. So the total number of expansions in an iterative deepening
search is-
That is,
Summation[(d + 1 - i) bi], from i = 0 to i = d
Which is same as O(bd)
After evaluating the above expression, we find that asymptotically IDDFS takes the same
time as that of DFS and BFS, but it is indeed slower than both of them as it has a higher
constant factor in its time complexity expression.
IDDFS is best suited for a complete infinite tree
References:
https://en.wikipedia.org/wiki/Iterative_deepening_depth-first_search
Source
https://www.geeksforgeeks.org/iterative-deepening-searchids-iterative-deepening-depth-first-searchiddfs/
1261
Chapter 179
1262
Chapter 179. Java Program for Dijkstra’s Algorithm with Path Printing
}
}
distance = matrix[0]; //initialize the distance array
visited[0] = 1; //set the source node as visited
distance[0] = 0; //set the distance from source to source to zero which is the starting p
for (int counter = 0; counter < 5; counter++)
{
min = 999;
for (int i = 0; i < 5; i++)
{
if (min > distance[i] && visited[i]!=1)
{
min = distance[i];
nextNode = i;
}
}
visited[nextNode] = 1;
for (int i = 0; i < 5; i++)
{
if (visited[i]!=1)
{
if (min+matrix[nextNode][i] < distance[i])
{
distance[i] = min+matrix[nextNode][i];
preD[i] = nextNode;
}
}
}
}
for(int i = 0; i < 5; i++)
System.out.print("|" + distance[i]);
System.out.println("|");
int j;
for (int i = 0; i < 5; i++)
{
if (i!=0)
{
System.out.print("Path = " + i);
1263
Chapter 179. Java Program for Dijkstra’s Algorithm with Path Printing
j = i;
do
{
j = preD[j];
System.out.print(" <- " + j);
}
while(j != 0);
}
System.out.println();
}
}
}
This program is contributed by by Raj Miglani. Please write comments if you find anything
incorrect, or you want to share more information about the topic discussed above
Source
https://www.geeksforgeeks.org/java-program-for-dijkstras-algorithm-with-path-printing/
1264
Chapter 180
k’th heaviest adjacent node in a graph where each vertex has weight - GeeksforGeeks
Given a positive number k and an undirected graph of N nodes, numbered from 0 to N-1,
each having a weight associated with it. Note that this is different from a normal weighted
graph where every edge has a weight.
For each node, if we sort the nodes (according to their weights), which are directly connected
to it, in decreasing order, then what will be the number of the node at the kth position.
Print kth node number(not weight) for each node and if it does not exist, print -1.
Examples:
Input : N = 3, k = 2, wt[] = { 2, 4, 3 }.
edge 1: 0 2
edge 2: 0 1
edge 3: 1 2
Output : 2 0 0
Graph:
0 (weight 2)
/ \
/ \
1-----2
(weight 4) (weight 3)
For node 0, sorted (decreasing order) nodes
according to their weights are node 1(weight 4),
node 2(weight 3). The node at 2nd position for
1265
Chapter 180. k’th heaviest adjacent node in a graph where each vertex has weight
node 0 is node 2.
For node 1, sorted (decreasing order) nodes
according to their weight are node 2(weight 3),
node 0(weight 2). The node at 2nd position for
node 1 is node 0.
For node 2, sorted (decreasing order) nodes
according to their weight are node 1(weight 4),
node 0(weight 2). The node at 2nd position for
node 2 is node 0.
The idea is to sort Adjacency List of each node on the basis of adjacent node weights.
First, create Adjacency List for all the nodes. Now for each node, all the nodes which are
directly connected to it stored in a list. In adjacency list, store the nodes along with their
weights.
Now, for each node sort the weights of all nodes which are directly connected to it in reverse
order, and then print the node number which is at kth position in the list of each node.
Below is C++ implementation of this approach:
1266
Chapter 180. k’th heaviest adjacent node in a graph where each vertex has weight
int wt[] = { 2, 4, 3 };
// Making adjacency list, storing the nodes
// along with their weight.
vector< pair<int, int> > adj[n+1];
adj[0].push_back(make_pair(wt[2], 2));
adj[2].push_back(make_pair(wt[0], 0));
adj[0].push_back(make_pair(wt[1], 1));
adj[1].push_back(make_pair(wt[0], 0));
adj[1].push_back(make_pair(wt[2], 2));
adj[2].push_back(make_pair(wt[1], 1));
printkthnode(adj, wt, n, k);
return 0;
}
Output:
2 0 0
Source
https://www.geeksforgeeks.org/kth-adjacent-node-graph-vertex-weight/
1267
Chapter 181
A DFS based solution to find a topological sort has already been discussed.
In this article we will see another way to find the linear ordering of vertices in a directed
acyclic graph (DAG). The approach is based on the below fact :
1268
Chapter 181. Kahn’s algorithm for Topological Sorting
A DAG G has at least one vertex with in-degree 0 and one vertex with out-
degree 0.
Proof: There’s a simple proof to the above fact is that a DAG does not contain a cycle
which means that all paths will be of finite length. Now let S be the longest path from
u(source) to v(destination). Since S is the longest path there can be no incoming edge to u
and no outgoing edge from v, if this situation had occurred then S would not have been the
longest path
=> indegree(u) = 0 and outdegree(v) = 0
Algorithm:
Steps involved in finding the topological ordering of a DAG:
Step-1: Compute in-degree (number of incoming edges) for each of the vertex present in
the DAG and initialize the count of visited nodes as 0.
Step-2: Pick all the vertices with in-degree as 0 and add them into a queue (Enqueue
operation)
Step-3: Remove a vertex from the queue (Dequeue operation) and then.
1269
Chapter 181. Kahn’s algorithm for Topological Sorting
Time Complexity: The outer for loop will be executed V number of times and the inner for
loop will be executed E number of times, Thus overall time complexity is O(V+E).
The overall time complexity of the algorithm is O(V+E)
Below is C++ implementation of above algorithm. The implementation uses method 2
discussed above for finding indegrees.
C++
1270
Chapter 181. Kahn’s algorithm for Topological Sorting
// Traverse adjacency lists to fill indegrees of
// vertices. This step takes O(V+E) time
for (int u=0; u<V; u++)
{
list<int>::iterator itr;
for (itr = adj[u].begin(); itr != adj[u].end(); itr++)
in_degree[*itr]++;
}
// Create an queue and enqueue all vertices with
// indegree 0
queue<int> q;
for (int i = 0; i < V; i++)
if (in_degree[i] == 0)
q.push(i);
// Initialize count of visited vertices
int cnt = 0;
// Create a vector to store result (A topological
// ordering of the vertices)
vector <int> top_order;
// One by one dequeue vertices from queue and enqueue
// adjacents if indegree of adjacent becomes 0
while (!q.empty())
{
// Extract front of queue (or perform dequeue)
// and add it to topological order
int u = q.front();
q.pop();
top_order.push_back(u);
// Iterate through all its neighbouring nodes
// of dequeued node u and decrease their in-degree
// by 1
list<int>::iterator itr;
for (itr = adj[u].begin(); itr != adj[u].end(); itr++)
// If in-degree becomes zero, add it to queue
if (--in_degree[*itr] == 0)
q.push(*itr);
cnt++;
}
// Check if there was a cycle
1271
Chapter 181. Kahn’s algorithm for Topological Sorting
if (cnt != V)
{
cout << "There exists a cycle in the graph\n";
return;
}
// Print topological order
for (int i=0; i<top_order.size(); i++)
cout << top_order[i] << " ";
cout << endl;
}
// Driver program to test above functions
int main()
{
// Create a graph given in the above diagram
Graph g(6);
g.addEdge(5, 2);
g.addEdge(5, 0);
g.addEdge(4, 0);
g.addEdge(4, 1);
g.addEdge(2, 3);
g.addEdge(3, 1);
cout << "Following is a Topological Sort of\n";
g.topologicalSort();
return 0;
}
Java
1272
Chapter 181. Kahn’s algorithm for Topological Sorting
1273
Chapter 181. Kahn’s algorithm for Topological Sorting
topOrder.add(u);
// Iterate through all its neighbouring nodes
// of dequeued node u and decrease their in-degree
// by 1
for(int node : adj[u])
{
// If in-degree becomes zero, add it to queue
if(--indegree[node] == 0)
q.add(node);
}
cnt++;
}
// Check if there was a cycle
if(cnt != V)
{
System.out.println("There exists a cycle in the graph");
return ;
}
// Print topological order
for(int i : topOrder)
{
System.out.print(i+" ");
}
}
}
// Driver program to test above functions
class Main
{
public static void main(String args[])
{
// Create a graph given in the above diagram
Graph g=new Graph(6);
g.addEdge(5, 2);
g.addEdge(5, 0);
g.addEdge(4, 0);
g.addEdge(4, 1);
g.addEdge(2, 3);
g.addEdge(3, 1);
System.out.println("Following is a Topological Sort");
g.topologicalSort();
}
}
Python
1274
Chapter 181. Kahn’s algorithm for Topological Sorting
1275
Chapter 181. Kahn’s algorithm for Topological Sorting
u = queue.pop(0)
top_order.append(u)
# Iterate through all neighbouring nodes
# of dequeued node u and decrease their in-degree
# by 1
for i in self.graph[u]:
in_degree[i] -= 1
# If in-degree becomes zero, add it to queue
if in_degree[i] == 0:
queue.append(i)
cnt += 1
# Check if there was a cycle
if cnt != self.V:
print "There exists a cycle in the graph"
else :
#Print topological order
print top_order
g= Graph(6)
g.addEdge(5, 2);
g.addEdge(5, 0);
g.addEdge(4, 0);
g.addEdge(4, 1);
g.addEdge(2, 3);
g.addEdge(3, 1);
print "Following is a Topological Sort of the given graph"
g.topologicalSort()
# This code is contributed by Neelam Yadav
Output :
This article is contributed by Chirag Agarwal. Please write comments if you find anything
incorrect, or you want to share more information about the topic discussed above
Source
https://www.geeksforgeeks.org/topological-sorting-indegree-based-solution/
1276
Chapter 182
Karger’s algorithm for Minimum Cut Set 1 (Introduction and Implementation) - Geeks-
forGeeks
Given an undirected and unweighted graph, find the smallest cut (smallest number of edges
that disconnects the graph into two components).
The input graph may have parallel edges.
For example consider the following example, the smallest cut has 2 edges.
A Simple Solution use Max-Flow based s-t cut algorithm to find minimum cut. Consider
every pair of vertices as source ‘s’ and sink ‘t’, and call minimum s-t cut algorithm to find
1277
Chapter 182. Karger’s algorithm for Minimum Cut Set 1 (Introduction and
Implementation)
the s-t cut. Return minimum of all s-t cuts. Best possible time complexity of this algorithm
is O(V5 ) for a graph. [How? there are total possible V2 pairs and s-t cut algorithm for one
pair takes O(V*E) time and E = O(V2 )].
Below is simple Karger’s Algorithm for this purpose. Below Karger’s algorithm can be
implemented in O(E) = O(V2 ) time.
Let the next randomly picked edge be ‘d’. We remove this edge and combine vertices (0,1)
and 3.
1278
Chapter 182. Karger’s algorithm for Minimum Cut Set 1 (Introduction and
Implementation)
Now graph has two vertices, so we stop. The number of edges in the resultant graph is the
cut produced by Karger’s algorithm.
Karger’s algorithm is a Monte Carlo algorithm and cut produced by it may not
be minimum. For example, the following diagram shows that a different order of picking
random edges produces a min-cut of size 3.
1279
Chapter 182. Karger’s algorithm for Minimum Cut Set 1 (Introduction and
Implementation)
// graph is represented as an array of edges.
// Since the graph is undirected, the edge
// from src to dest is also edge from dest
// to src. Both are counted as 1 edge here.
Edge* edge;
};
// A structure to represent a subset for union-find
struct subset
{
int parent;
int rank;
};
// Function prototypes for union-find (These functions are defined
// after kargerMinCut() )
int find(struct subset subsets[], int i);
void Union(struct subset subsets[], int x, int y);
// A very basic implementation of Karger's randomized
// algorithm for finding the minimum cut. Please note
// that Karger's algorithm is a Monte Carlo Randomized algo
// and the cut returned by the algorithm may not be
// minimum always
int kargerMinCut(struct Graph* graph)
{
// Get data of given graph
int V = graph->V, E = graph->E;
Edge *edge = graph->edge;
// Allocate memory for creating V subsets.
struct subset *subsets = new subset[V];
// Create V subsets with single elements
for (int v = 0; v < V; ++v)
{
subsets[v].parent = v;
subsets[v].rank = 0;
}
// Initially there are V vertices in
// contracted graph
int vertices = V;
// Keep contracting vertices until there are
// 2 vertices.
while (vertices > 2)
1280
Chapter 182. Karger’s algorithm for Minimum Cut Set 1 (Introduction and
Implementation)
{
// Pick a random edge
int i = rand() % E;
// Find vertices (or sets) of two corners
// of current edge
int subset1 = find(subsets, edge[i].src);
int subset2 = find(subsets, edge[i].dest);
// If two corners belong to same subset,
// then no point considering this edge
if (subset1 == subset2)
continue;
// Else contract the edge (or combine the
// corners of edge into one vertex)
else
{
printf("Contracting edge %d-%d\n",
edge[i].src, edge[i].dest);
vertices--;
Union(subsets, subset1, subset2);
}
}
// Now we have two vertices (or subsets) left in
// the contracted graph, so count the edges between
// two components and return the count.
int cutedges = 0;
for (int i=0; i<E; i++)
{
int subset1 = find(subsets, edge[i].src);
int subset2 = find(subsets, edge[i].dest);
if (subset1 != subset2)
cutedges++;
}
return cutedges;
}
// A utility function to find set of an element i
// (uses path compression technique)
int find(struct subset subsets[], int i)
{
// find root and make root as parent of i
// (path compression)
if (subsets[i].parent != i)
subsets[i].parent =
1281
Chapter 182. Karger’s algorithm for Minimum Cut Set 1 (Introduction and
Implementation)
find(subsets, subsets[i].parent);
return subsets[i].parent;
}
// A function that does union of two sets of x and y
// (uses union by rank)
void Union(struct subset subsets[], int x, int y)
{
int xroot = find(subsets, x);
int yroot = find(subsets, y);
// Attach smaller rank tree under root of high
// rank tree (Union by Rank)
if (subsets[xroot].rank < subsets[yroot].rank)
subsets[xroot].parent = yroot;
else if (subsets[xroot].rank > subsets[yroot].rank)
subsets[yroot].parent = xroot;
// If ranks are same, then make one as root and
// increment its rank by one
else
{
subsets[yroot].parent = xroot;
subsets[xroot].rank++;
}
}
// Creates a graph with V vertices and E edges
struct Graph* createGraph(int V, int E)
{
Graph* graph = new Graph;
graph->V = V;
graph->E = E;
graph->edge = new Edge[E];
return graph;
}
// Driver program to test above functions
int main()
{
/* Let us create following unweighted graph
0------1
| \ |
| \ |
| \|
2------3 */
int V = 4; // Number of vertices in graph
1282
Chapter 182. Karger’s algorithm for Minimum Cut Set 1 (Introduction and
Implementation)
Output:
Note that the above program is based on outcome of a random function and may
produce different output.
In this post, we have discussed simple Karger’s algorithm and have seen that the algorithm
doesn’t always produce min-cut. The above algorithm produces min-cut with probability
greater or equal to that 1/(n2 ). See next post on Analysis and Applications of Karger’s
Algortihm, applications, proof of this probability and improvements are discussed.
References:
http://en.wikipedia.org/wiki/Karger%27s_algorithm
1283
Chapter 182. Karger’s algorithm for Minimum Cut Set 1 (Introduction and
Implementation)
https://www.youtube.com/watch?v=P0l8jMDQTEQ
https://www.cs.princeton.edu/courses/archive/fall13/cos521/lecnotes/lec2final.pdf
http://web.stanford.edu/class/archive/cs/cs161/cs161.1138/lectures/11/Small11.pdf
Source
https://www.geeksforgeeks.org/kargers-algorithm-for-minimum-cut-set-1-introduction-and-implementation/
1284
Chapter 183
Output : 1.66667
1285
Chapter 183. Karp’s minimum mean (or average) weight cycle algorithm
where 0<=k<=n-1
Please refer solution of problem 9.2 here for proof that above steps find minimum average
weight.
1286
Chapter 183. Karp’s minimum mean (or average) weight cycle algorithm
{
if (dp[i-1][edges[j][k].from] != -1)
{
int curr_wt = dp[i-1][edges[j][k].from] +
edges[j][k].weight;
if (dp[i][j] == -1)
dp[i][j] = curr_wt;
else
dp[i][j] = min(dp[i][j], curr_wt);
}
}
}
}
}
// Returns minimum value of average weight of a
// cycle in graph.
double minAvgWeight()
{
int dp[V+1][V];
shortestpath(dp);
// array to store the avg values
double avg[V];
for (int i=0; i<V; i++)
avg[i] = -1;
// Compute average values for all vertices using
// weights of shortest paths store in dp.
for (int i=0; i<V; i++)
{
if (dp[V][i] != -1)
{
for (int j=0; j<V; j++)
if (dp[j][i] != -1)
avg[i] = max(avg[i],
((double)dp[V][i]-dp[j][i])/(V-j));
}
}
// Find minimum value in avg[]
double result = avg[0];
for (int i=0; i<V; i++)
if (avg[i] != -1 && avg[i] < result)
result = avg[i];
return result;
}
1287
Chapter 183. Karp’s minimum mean (or average) weight cycle algorithm
// Driver function
int main()
{
addedge(0, 1, 1);
addedge(0, 2, 10);
addedge(1, 2, 3);
addedge(2, 3, 2);
addedge(3, 1, 0);
addedge(3, 0, 8);
cout << minAvgWeight();
return 0;
}
Output:
1.66667
Source
https://www.geeksforgeeks.org/karps-minimum-mean-average-weight-cycle-algorithm/
1288
Chapter 184
A simple social network: the nodes represent people or actors and the edges between nodes
represent some relationship between actors
Katz centrality computes the relative influence of a node within a network by measuring
1289
Chapter 184. Katz Centrality (Centrality Measure)
the number of the immediate neighbors (first degree nodes) and also all other nodes in the
network that connect to the node under consideration through these immediate neighbors.
Connections made with distant neighbors are, however, penalized by an attenuation factor
. Each path or connection between a pair of nodes is assigned a weight determined by
Agneta and John through Aziz and Jane will be and the weight
assigned to the connection between Agneta and John through Diego, Jose and Bob will be
.
Mathematical formulation
Note that the above definition uses the fact that the element at location of the
adjacency matrix raised to the power (i.e. ) reflects the total number of
degree connections between nodes and . The value of the attenuation factor has
to be chosen such that it is smaller than the reciprocal of the absolute value of the largest
eigenvalue of the adjacency matrix A. In this case the following expression can be used to
calculate Katz centrality:
Here is the identity matrix, is an identity vector of size n (n is the number of nodes)
1290
Chapter 184. Katz Centrality (Centrality Measure)
1291
Chapter 184. Katz Centrality (Centrality Measure)
Parameters
----------
G : graph
A NetworkX graph
alpha : float
Attenuation factor
beta : scalar or dictionary, optional (default=1.0)
Weight attributed to the immediate neighborhood.
If not a scalar, the dictionary must have an value
for every node.
max_iter : integer, optional (default=1000)
Maximum number of iterations in power method.
tol : float, optional (default=1.0e-6)
Error tolerance used to check convergence in
power method iteration.
nstart : dictionary, optional
Starting value of Katz iteration for each node.
normalized : bool, optional (default=True)
If True normalize the resulting values.
weight : None or string, optional
If None, all edge weights are considered equal.
Otherwise holds the name of the edge attribute
used as weight.
Returns
-------
nodes : dictionary
Dictionary of nodes with Katz centrality as
the value.
Raises
------
NetworkXError
If the parameter `beta` is not a scalar but
lacks a value for at least one node
Notes
1292
Chapter 184. Katz Centrality (Centrality Measure)
-----
This algorithm it uses the power method to find
the eigenvector corresponding to the largest
eigenvalue of the adjacency matrix of G.
The constant alpha should be strictly less than
the inverse of largest eigenvalue of the adjacency
matrix for the algorithm to converge.
The iteration will stop after max_iter iterations
or an error tolerance ofnumber_of_nodes(G)*tol
has been reached.
When `\alpha = 1/\lambda_{max}` and `\beta=0`,
Katz centrality is the same as eigenvector centrality.
For directed graphs this finds "left" eigenvectors
which corresponds to the in-edges in the graph.
For out-edges Katz centrality first reverse the
graph with G.reverse().
"""
from math import sqrt
if len(G) == 0:
return {}
nnodes = G.number_of_nodes()
if nstart is None:
# choose starting vector with entries of 0
x = dict([(n,0) for n in G])
else:
x = nstart
try:
b = dict.fromkeys(G,float(beta))
except (TypeError,ValueError,AttributeError):
b = beta
if set(beta) != set(G):
raise nx.NetworkXError('beta dictionary '
'must have a value for every node')
# make up to max_iter iterations
for i in range(max_iter):
xlast = x
x = dict.fromkeys(xlast, 0)
1293
Chapter 184. Katz Centrality (Centrality Measure)
# do the multiplication y^T = Alpha * x^T A - Beta
for n in x:
for nbr in G[n]:
x[nbr] += xlast[n] * G[n][nbr].get(weight, 1)
for n in x:
x[n] = alpha*x[n] + b[n]
# check convergence
err = sum([abs(x[n]-xlast[n]) for n in x])
if err < nnodes*tol:
if normalized:
# normalize vector
try:
s = 1.0/sqrt(sum(v**2 for v in x.values()))
# this should never be zero?
except ZeroDivisionError:
s = 1.0
else:
s = 1
for n in x:
x[n] *= s
return x
raise nx.NetworkXError('Power iteration failed to converge in '
'%d iterations.' % max_iter)
The above function is invoked using the networkx library and once the library is installed,
you can eventually use it and the following code has to be written in python for the imple-
mentation of the katz centrality of a node.
0 0.37
1 0.60
2 0.60
3 0.37
1294
Chapter 184. Katz Centrality (Centrality Measure)
The above result is a dictionary depicting the value of katz centrality of each node. The
above is an extension of my article series on the centrality measures. Keep networking!!!
References
http://networkx.readthedocs.io/en/networkx-1.10/index.html
https://en.wikipedia.org/wiki/Katz_centrality
Source
https://www.geeksforgeeks.org/katz-centrality-centrality-measure/
1295
Chapter 185
We have discussed one implementation of Kruskal’s algorithm in previous post. In this post,
a simpler implementation for adjacency matrix is discussed.
1296
Chapter 185. Kruskal’s Algorithm (Simple Implementation for Adjacency Matrix)
}
// Does union of i and j. It returns
// false if i and j are already in same
// set.
void union1(int i, int j)
{
int a = find(i);
int b = find(j);
parent[a] = b;
}
// Finds MST using Kruskal's algorithm
void kruskalMST(int cost[][V])
{
int mincost = 0; // Cost of min MST.
// Initialize sets of disjoint sets.
for (int i = 0; i < V; i++)
parent[i] = i;
// Include minimum weight edges one by one
int edge_count = 0;
while (edge_count < V - 1) {
int min = INT_MAX, a = -1, b = -1;
for (int i = 0; i < V; i++) {
for (int j = 0; j < V; j++) {
if (find(i) != find(j) && cost[i][j] < min) {
min = cost[i][j];
a = i;
b = j;
}
}
}
union1(a, b);
printf("Edge %d:(%d, %d) cost:%d \n",
edge_count++, a, b, min);
mincost += min;
}
printf("\n Minimum cost= %d \n", mincost);
}
// driver program to test above function
int main()
{
/* Let us create the following graph
2 3
1297
Chapter 185. Kruskal’s Algorithm (Simple Implementation for Adjacency Matrix)
(0)--(1)--(2)
| / \ |
6| 8/ \5 |7
| / \ |
(3)-------(4)
9 */
int cost[][V] = {
{ INT_MAX, 2, INT_MAX, 6, INT_MAX },
{ 2, INT_MAX, 3, 8, 5 },
{ INT_MAX, 3, INT_MAX, INT_MAX, 7 },
{ 6, 8, INT_MAX, INT_MAX, 9 },
{ INT_MAX, 5, 7, 9, INT_MAX },
};
// Print the solution
kruskalMST(cost);
return 0;
}
Output:
Minimum cost= 16
Note that the above solution is not efficient. The idea is to provide a simple implementation
for adjacency matrix representations. Please see below for efficient implementations.
Kruskal’s Minimum Spanning Tree Algorithm Greedy Algo-2
Kruskal’s Minimum Spanning Tree using STL in C++
Source
https://www.geeksforgeeks.org/kruskals-algorithm-simple-implementation-for-adjacency-matrix/
1298
Chapter 186
The step#2 uses Union-Find algorithm to detect cycle. So we recommend to read following
post as a prerequisite.
Union-Find Algorithm Set 1 (Detect Cycle in a Graph)
Union-Find Algorithm Set 2 (Union By Rank and Path Compression)
The algorithm is a Greedy Algorithm. The Greedy Choice is to pick the smallest weight
edge that does not cause a cycle in the MST constructed so far. Let us understand it with
an example: Consider the below input graph.
1299
Chapter 186. Kruskal’s Minimum Spanning Tree Algorithm Greedy Algo-2
The graph contains 9 vertices and 14 edges. So, the minimum spanning tree formed will be
having (9 – 1) = 8 edges.
After sorting:
Weight Src Dest
1 7 6
2 8 2
2 6 5
4 0 1
4 2 5
6 8 6
7 2 3
7 7 8
8 0 7
8 1 2
9 3 4
10 5 4
11 1 7
14 3 5
Now pick all edges one by one from sorted list of edges
1. Pick edge 7-6: No cycle is formed, include it.
1300
Chapter 186. Kruskal’s Minimum Spanning Tree Algorithm Greedy Algo-2
6. Pick edge 8-6: Since including this edge results in cycle, discard it.
7. Pick edge 2-3: No cycle is formed, include it.
8. Pick edge 7-8: Since including this edge results in cycle, discard it.
9. Pick edge 0-7: No cycle is formed, include it.
1301
Chapter 186. Kruskal’s Minimum Spanning Tree Algorithm Greedy Algo-2
10. Pick edge 1-2: Since including this edge results in cycle, discard it.
11. Pick edge 3-4: No cycle is formed, include it.
Since the number of edges included equals (V – 1), the algorithm stops here.
C/C++
1302
Chapter 186. Kruskal’s Minimum Spanning Tree Algorithm Greedy Algo-2
1303
Chapter 186. Kruskal’s Minimum Spanning Tree Algorithm Greedy Algo-2
1304
Chapter 186. Kruskal’s Minimum Spanning Tree Algorithm Greedy Algo-2
result[e++] = next_edge;
Union(subsets, x, y);
}
// Else discard the next_edge
}
// print the contents of result[] to display the
// built MST
printf("Following are the edges in the constructed MST\n");
for (i = 0; i < e; ++i)
printf("%d -- %d == %d\n", result[i].src, result[i].dest,
result[i].weight);
return;
}
// Driver program to test above functions
int main()
{
/* Let us create following weighted graph
10
0--------1
| \ |
6| 5\ |15
| \ |
2--------3
4 */
int V = 4; // Number of vertices in graph
int E = 5; // Number of edges in graph
struct Graph* graph = createGraph(V, E);
// add edge 0-1
graph->edge[0].src = 0;
graph->edge[0].dest = 1;
graph->edge[0].weight = 10;
// add edge 0-2
graph->edge[1].src = 0;
graph->edge[1].dest = 2;
graph->edge[1].weight = 6;
// add edge 0-3
graph->edge[2].src = 0;
graph->edge[2].dest = 3;
graph->edge[2].weight = 5;
// add edge 1-3
graph->edge[3].src = 1;
1305
Chapter 186. Kruskal’s Minimum Spanning Tree Algorithm Greedy Algo-2
graph->edge[3].dest = 3;
graph->edge[3].weight = 15;
// add edge 2-3
graph->edge[4].src = 2;
graph->edge[4].dest = 3;
graph->edge[4].weight = 4;
KruskalMST(graph);
return 0;
}
Java
1306
Chapter 186. Kruskal’s Minimum Spanning Tree Algorithm Greedy Algo-2
{
V = v;
E = e;
edge = new Edge[E];
for (int i=0; i<e; ++i)
edge[i] = new Edge();
}
// A utility function to find set of an element i
// (uses path compression technique)
int find(subset subsets[], int i)
{
// find root and make root as parent of i (path compression)
if (subsets[i].parent != i)
subsets[i].parent = find(subsets, subsets[i].parent);
return subsets[i].parent;
}
// A function that does union of two sets of x and y
// (uses union by rank)
void Union(subset subsets[], int x, int y)
{
int xroot = find(subsets, x);
int yroot = find(subsets, y);
// Attach smaller rank tree under root of high rank tree
// (Union by Rank)
if (subsets[xroot].rank < subsets[yroot].rank)
subsets[xroot].parent = yroot;
else if (subsets[xroot].rank > subsets[yroot].rank)
subsets[yroot].parent = xroot;
// If ranks are same, then make one as root and increment
// its rank by one
else
{
subsets[yroot].parent = xroot;
subsets[xroot].rank++;
}
}
// The main function to construct MST using Kruskal's algorithm
void KruskalMST()
{
Edge result[] = new Edge[V]; // Tnis will store the resultant MST
int e = 0; // An index variable, used for result[]
int i = 0; // An index variable, used for sorted edges
1307
Chapter 186. Kruskal’s Minimum Spanning Tree Algorithm Greedy Algo-2
1308
Chapter 186. Kruskal’s Minimum Spanning Tree Algorithm Greedy Algo-2
1309
Chapter 186. Kruskal’s Minimum Spanning Tree Algorithm Greedy Algo-2
}
//This code is contributed by Aakash Hasija
Python
1310
Chapter 186. Kruskal’s Minimum Spanning Tree Algorithm Greedy Algo-2
rank[xroot] += 1
# The main function to construct MST using Kruskal's
# algorithm
def KruskalMST(self):
result =[] #This will store the resultant MST
i = 0 # An index variable, used for sorted edges
e = 0 # An index variable, used for result[]
# Step 1: Sort all the edges in non-decreasing
# order of their
# weight. If we are not allowed to change the
# given graph, we can create a copy of graph
self.graph = sorted(self.graph,key=lambda item: item[2])
parent = [] ; rank = []
# Create V subsets with single elements
for node in range(self.V):
parent.append(node)
rank.append(0)
# Number of edges to be taken is equal to V-1
while e < self.V -1 :
# Step 2: Pick the smallest edge and increment
# the index for next iteration
u,v,w = self.graph[i]
i = i + 1
x = self.find(parent, u)
y = self.find(parent ,v)
# If including this edge does't cause cycle,
# include it in result and increment the index
# of result for next edge
if x != y:
e = e + 1
result.append([u,v,w])
self.union(parent, rank, x, y)
# Else discard the edge
# print the contents of result[] to display the built MST
print "Following are the edges in the constructed MST"
for u,v,weight in result:
#print str(u) + " -- " + str(v) + " == " + str(weight)
print ("%d -- %d == %d" % (u,v,weight))
1311
Chapter 186. Kruskal’s Minimum Spanning Tree Algorithm Greedy Algo-2
# Driver code
g = Graph(4)
g.addEdge(0, 1, 10)
g.addEdge(0, 2, 6)
g.addEdge(0, 3, 5)
g.addEdge(1, 3, 15)
g.addEdge(2, 3, 4)
g.KruskalMST()
#This code is contributed by Neelam Yadav
Time Complexity: O(ElogE) or O(ElogV). Sorting of edges takes O(ELogE) time. After
sorting, we iterate through all edges and apply find-union algorithm. The find and union
operations can take atmost O(LogV) time. So overall complexity is O(ELogE + ELogV)
time. The value of E can be atmost O(V2 ), so O(LogV) are O(LogE) same. Therefore,
overall time complexity is O(ElogE) or O(ElogV)
References:
http://www.ics.uci.edu/~eppstein/161/960206.html
http://en.wikipedia.org/wiki/Minimum_spanning_tree
This article is compiled by Aashish Barnwal and reviewed by GeeksforGeeks team. Please
write comments if you find anything incorrect, or you want to share more information about
the topic discussed above.
Source
https://www.geeksforgeeks.org/kruskals-minimum-spanning-tree-algorithm-greedy-algo-2/
1312
Chapter 187
Weight of MST is 37
1313
Chapter 187. Kruskal’s Minimum Spanning Tree using STL in C++
2. Pick the smallest edge. Check if it forms a cycle with the spanning tree formed so far.
If cycle is not formed, include this edge. Else, discard it.
3. Repeat step#2 until there are (V-1) edges in the spanning tree.
Here are some key points which will be useful for us in implementing the Kruskal’s algorithm
using STL.
1. Use a vector of edges which consist of all the edges in the graph and each item of a
vector will contain 3 parameters: source, destination and the cost of an edge between
the source and destination.
Here in the outer pair (i.e pair<int,pair<int,int> > ) the first element corresponds to
the cost of a edge while the second element is itself a pair, and it contains two vertices
of edge.
2. Use the inbuilt std::sort to sort the edges in the non-decreasing order; by default the
sort function sort in non-decreasing order.
3. We use the Union Find Algorithm to check if it the current edge forms a cycle if it is
added in the current MST. If yes discard it, else include it (union).
Pseudo Code:
// Initialize result
mst_weight = 0
1314
Chapter 187. Kruskal’s Minimum Spanning Tree using STL in C++
// weighted graph
#include<bits/stdc++.h>
using namespace std;
// Creating shortcut for an integer pair
typedef pair<int, int> iPair;
// Structure to represent a graph
struct Graph
{
int V, E;
vector< pair<int, iPair> > edges;
// Constructor
Graph(int V, int E)
{
this->V = V;
this->E = E;
}
// Utility function to add an edge
void addEdge(int u, int v, int w)
{
edges.push_back({w, {u, v}});
}
// Function to find MST using Kruskal's
// MST algorithm
int kruskalMST();
};
// To represent Disjoint Sets
struct DisjointSets
{
int *parent, *rnk;
int n;
// Constructor.
DisjointSets(int n)
{
// Allocate memory
this->n = n;
parent = new int[n+1];
rnk = new int[n+1];
// Initially, all vertices are in
// different sets and have rank 0.
for (int i = 0; i <= n; i++)
1315
Chapter 187. Kruskal’s Minimum Spanning Tree using STL in C++
{
rnk[i] = 0;
//every element is parent of itself
parent[i] = i;
}
}
// Find the parent of a node 'u'
// Path Compression
int find(int u)
{
/* Make the parent of the nodes in the path
from u--> parent[u] point to parent[u] */
if (u != parent[u])
parent[u] = find(parent[u]);
return parent[u];
}
// Union by rank
void merge(int x, int y)
{
x = find(x), y = find(y);
/* Make tree with smaller height
a subtree of the other tree */
if (rnk[x] > rnk[y])
parent[y] = x;
else // If rnk[x] <= rnk[y]
parent[x] = y;
if (rnk[x] == rnk[y])
rnk[y]++;
}
};
/* Functions returns weight of the MST*/
int Graph::kruskalMST()
{
int mst_wt = 0; // Initialize result
// Sort edges in increasing order on basis of cost
sort(edges.begin(), edges.end());
// Create disjoint sets
DisjointSets ds(V);
1316
Chapter 187. Kruskal’s Minimum Spanning Tree using STL in C++
1317
Chapter 187. Kruskal’s Minimum Spanning Tree using STL in C++
g.addEdge(4, 5, 10);
g.addEdge(5, 6, 2);
g.addEdge(6, 7, 1);
g.addEdge(6, 8, 6);
g.addEdge(7, 8, 7);
cout << "Edges of MST are \n";
int mst_wt = g.kruskalMST();
cout << "\nWeight of MST is " << mst_wt;
return 0;
}
Output :
Weight of MST is 37
Optimization:
The above code can be optimized to stop the main loop of Kruskal when number of selected
edges become V-1. We know that MST has V-1 edges and there is no point iterating after
V-1 edges are selected. We have not added this optimization to keep code simple.
References:
Introduction to Algorithms by Cormen Leiserson Rivest and Stein(CLRS) 3
Time complexity and step by step illustration are discussed in previous post on Kruskal’s
algorithm.
Source
https://www.geeksforgeeks.org/kruskals-minimum-spanning-tree-using-stl-in-c/
1318
Chapter 188
Input :
1319
Chapter 188. Largest connected component on a grid
Output : 9
Approach :
The approach is to visualize the given grid as a graph with each cell representing a separate
node of the graph and each node connected to four other nodes which are to immediately
up, down, left, and right of that grid. Now doing a BFS search for every node of the graph,
find all the nodes connected to the current node with same color value as the current node.
Here is the graph for above example :
1320
Chapter 188. Largest connected component on a grid
1321
Chapter 188. Largest connected component on a grid
int visited[n][m];
// result stores the final result grid
int result[n][m];
// stores the count of cells in the largest
// connected component
int COUNT;
// Function checks if a cell is valid i.e it
// is inside the grid and equal to the key
bool is_valid(int x, int y, int key, int input[n][m])
{
if (x < n && y < m && x >= 0 && y >= 0) {
if (visited[x][y] == false && input[x][y] == key)
return true;
else
return false;
}
else
return false;
}
// BFS to find all cells in
// connection with key = input[i][j]
void BFS(int x, int y, int i, int j, int input[n][m])
{
// terminating case for BFS
if (x != y)
return;
visited[i][j] = 1;
COUNT++;
// x_move and y_move arrays
// are the possible movements
// in x or y direction
int x_move[] = { 0, 0, 1, -1 };
int y_move[] = { 1, -1, 0, 0 };
// checks all four points connected with input[i][j]
for (int u = 0; u < 4; u++)
if (is_valid(i + y_move[u], j + x_move[u], x, input))
BFS(x, y, i + y_move[u], j + x_move[u], input);
}
// called every time before a BFS
// so that visited array is reset to zero
1322
Chapter 188. Largest connected component on a grid
void reset_visited()
{
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
visited[i][j] = 0;
}
// If a larger connected component
// is found this function is called
// to store information about that component.
void reset_result(int key, int input[n][m])
{
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (visited[i][j] && input[i][j] == key)
result[i][j] = visited[i][j];
else
result[i][j] = 0;
}
}
}
// function to print the result
void print_result(int res)
{
cout << "The largest connected "
<< "component of the grid is :" << res << "\n";
// prints the largest component
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (result[i][j])
cout << result[i][j] << " ";
else
cout << ". ";
}
cout << "\n";
}
}
// function to calculate the largest connected
// component
void computeLargestConnectedGrid(int input[n][m])
{
int current_max = INT_MIN;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
reset_visited();
1323
Chapter 188. Largest connected component on a grid
COUNT = 0;
// checking cell to the right
if (j + 1 < m)
BFS(input[i][j], input[i][j + 1], i, j, input);
// updating result
if (COUNT >= current_max) {
current_max = COUNT;
reset_result(input[i][j], input);
}
reset_visited();
COUNT = 0;
// checking cell downwards
if (i + 1 < n)
BFS(input[i][j], input[i + 1][j], i, j, input);
// updating result
if (COUNT >= current_max) {
current_max = COUNT;
reset_result(input[i][j], input);
}
}
}
print_result(current_max);
}
// Drivers Code
int main()
{
int input[n][m] = { { 1, 4, 4, 4, 4, 3, 3, 1 },
{ 2, 1, 1, 4, 3, 3, 1, 1 },
{ 3, 2, 1, 1, 2, 3, 2, 1 },
{ 3, 3, 2, 1, 2, 2, 2, 2 },
{ 3, 1, 3, 1, 1, 4, 4, 4 },
{ 1, 1, 3, 1, 1, 4, 4, 4 } };
// function to compute the largest
// connected component in the grid
computeLargestConnectedGrid(input);
return 0;
}
Java
1324
Chapter 188. Largest connected component on a grid
import java.lang.*;
import java.io.*;
class GFG
{
static final int n = 6;
static final int m = 8;
// stores information about which cell
// are already visited in a particular BFS
static final int visited[][] = new int [n][m];
// result stores the final result grid
static final int result[][] = new int [n][m];
// stores the count of
// cells in the largest
// connected component
static int COUNT;
// Function checks if a cell
// is valid i.e it is inside
// the grid and equal to the key
static boolean is_valid(int x, int y,
int key,
int input[][])
{
if (x < n && y < m &&
x >= 0 && y >= 0)
{
if (visited[x][y] == 0 &&
input[x][y] == key)
return true;
else
return false;
}
else
return false;
}
// BFS to find all cells in
// connection with key = input[i][j]
static void BFS(int x, int y, int i,
int j, int input[][])
{
// terminating case for BFS
if (x != y)
return;
1325
Chapter 188. Largest connected component on a grid
visited[i][j] = 1;
COUNT++;
// x_move and y_move arrays
// are the possible movements
// in x or y direction
int x_move[] = { 0, 0, 1, -1 };
int y_move[] = { 1, -1, 0, 0 };
// checks all four points
// connected with input[i][j]
for (int u = 0; u < 4; u++)
if ((is_valid(i + y_move[u],
j + x_move[u], x, input)) == true)
BFS(x, y, i + y_move[u],
j + x_move[u], input);
}
// called every time before
// a BFS so that visited
// array is reset to zero
static void reset_visited()
{
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
visited[i][j] = 0;
}
// If a larger connected component
// is found this function is
// called to store information
// about that component.
static void reset_result(int key,
int input[][])
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
if (visited[i][j] ==1 &&
input[i][j] == key)
result[i][j] = visited[i][j];
else
result[i][j] = 0;
}
}
}
1326
Chapter 188. Largest connected component on a grid
// function to print the result
static void print_result(int res)
{
System.out.println ("The largest connected " +
"component of the grid is :" +
res );
// prints the largest component
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
if (result[i][j] != 0)
System.out.print(result[i][j] + " ");
else
System.out.print(". ");
}
System.out.println();
}
}
// function to calculate the
// largest connected component
static void computeLargestConnectedGrid(int input[][])
{
int current_max = Integer.MIN_VALUE;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
reset_visited();
COUNT = 0;
// checking cell to the right
if (j + 1 < m)
BFS(input[i][j], input[i][j + 1],
i, j, input);
// updating result
if (COUNT >= current_max)
{
current_max = COUNT;
reset_result(input[i][j], input);
}
reset_visited();
COUNT = 0;
1327
Chapter 188. Largest connected component on a grid
// checking cell downwards
if (i + 1 < n)
BFS(input[i][j],
input[i + 1][j], i, j, input);
// updating result
if (COUNT >= current_max)
{
current_max = COUNT;
reset_result(input[i][j], input);
}
}
}
print_result(current_max);
}
// Driver Code
public static void main(String args[])
{
int input[][] = {{1, 4, 4, 4, 4, 3, 3, 1},
{2, 1, 1, 4, 3, 3, 1, 1},
{3, 2, 1, 1, 2, 3, 2, 1},
{3, 3, 2, 1, 2, 2, 2, 2},
{3, 1, 3, 1, 1, 4, 4, 4},
{1, 1, 3, 1, 1, 4, 4, 4}};
// function to compute the largest
// connected component in the grid
computeLargestConnectedGrid(input);
}
}
// This code is contributed by Subhadeep
Output:
Improved By : tufan_gupta2000
1328
Chapter 188. Largest connected component on a grid
Source
https://www.geeksforgeeks.org/largest-connected-component-on-a-grid/
1329
Chapter 189
Example 1:
Input : C[][]= {{0, 1, 2},
{1, 0, 3},
{2, 3, 0}}
Output : 3
Example 2:
Input : C[][]= {{0, 1, 1},
{1, 0, 3},
{1, 3, 0}}
Output : 0
Since graph is complete, each edge can be one of n*(n-1)/2 +1 different colors. These colors
are labeled from 0 to n*(n-1)/2, inclusive. But not all these n*(n-1)/2 +1 colors need to be
used. i.e., it is possible that two different edges could have the same color.
Let’s call a vertex “bad” if all its neighbors are of the same color. Obviously, we can’t have
any such bad vertex in our subset, so remove such bad vertex from the graph. This might
1330
Chapter 189. Largest subset of Graph vertices with edges of 2 or more colors
introduce some more bad vertices, but we can keep repeating this process until we find a
subset free of bad vertices. So, at last, we should remain through a graph which does not
have any bad vertex means every vertex of our subset has at least two different color edges
with other adjacent vertices.
Example:
Input :
let C[6][6]:
{{0, 9, 2, 4, 7, 8},
{9, 0, 9, 9, 7, 9},
{2, 9, 0, 3, 7, 6},
{4, 9, 3, 0, 7, 1},
{7, 7, 7, 7, 0, 7},
{8, 9, 6, 1, 7, 0}};
1331
Chapter 189. Largest subset of Graph vertices with edges of 2 or more colors
Step I: First of all, we can see that row 5(node ‘e’) contains only 7 means node ‘e’ is
connected through edges having color code 7 so it does not have more than one color edge
so we have to remove 5 from subset. Now, our graph will contain only 5 vertex and are as:
C[5][5]:
{{0, 9, 2, 4, 8},
{9, 0, 9, 9, 9},
{2, 9, 0, 3, 6},
{4, 9, 3, 0, 1},
{8, 9, 6, 1, 0}};
Step II: Further, we can see that row 2 (node ‘b’) also doesn’t contain more than 1 color
edge, so we should remove row 2 and column 2 also. Which result in our new graph as:
C[4][4]:
{{0, 2, 4, 8},
1332
Chapter 189. Largest subset of Graph vertices with edges of 2 or more colors
{2, 0, 3, 6},
{4, 3, 0, 1},
{8, 6, 1, 0}};
Step III: Now, we can see that each vertex has more than 1 different color edge. So, the
total number of vertices in the subset is 4.
1333
Chapter 189. Largest subset of Graph vertices with edges of 2 or more colors
// function to calculate max subset size
int subsetGraph(int C[][N])
{
// set for number of vertices
set<int> vertices;
for (int i = 0; i < N; ++i)
vertices.insert(i);
// loop for deletion of vertex from set
while (!vertices.empty())
{
// if subset has only 1 vertex return 0
if (vertices.size() == 1)
return 1;
// for each vertex iterate and keep removing
// a vertix while we find a vertex with all
// edges of same color.
bool someone_removed = false;
for (int x : vertices)
{
// note down different color values
// for each vertex
set<int> values;
for (int y : vertices)
if (y != x)
values.insert(C[x][y]);
// if only one color is found
// erase that vertex (bad vertex)
if (values.size() == 1)
{
vertices.erase(x);
someone_removed = true;
break;
}
}
// If no vertex was removed in the
// above loop.
if (!someone_removed)
break;
}
return (vertices.size());
}
1334
Chapter 189. Largest subset of Graph vertices with edges of 2 or more colors
// Driver program
int main()
{
int C[][N] = {{0, 9, 2, 4, 7, 8},
{9, 0, 9, 9, 7, 9},
{2, 9, 0, 3, 7, 6},
{4, 9, 3, 0, 7, 1},
{7, 7, 7, 7, 0, 7},
{8, 9, 6, 1, 7, 0}
};
cout << subsetGraph(C);
return 0;
}
Output:
Source
https://www.geeksforgeeks.org/largest-subset-graph-vertices-edges-2-colors/
1335
Chapter 190
1336
Chapter 190. Level Ancestor Problem
Below is the algorithm to fill the ancestor matrix and depth of each node using dynamic
programming. Here, we denote root node as R and initially assume the ancestor of root
node as 0. We also initialize depth array with -1 means the depth of the current node is
not set and we need to find its depth. If the depth of the current node is not equal to -1
means we have already computed its depth.
In the given figure we need to compute 1st level ancestor of the node with value 8. First,
we make ancestor matrix which stores 2ith ancestor of nodes. Now, 20 ancestor of node 8
is 10 and similarly 20 ancestor of node 10 is 9 and for node 9 it is 1 and for node 1 it is 5.
Based on the above algorithm 1st level ancestor of node 8 is( depth(8)-1 )th ancestor of
node 8. We have pre computed depth of each node and depth of 8 is 5 so we finally need to
find (5-1) = 4th ancestor of node 8 which is equal to 21 th ancestor of [21 ancestor of
1337
Chapter 190. Level Ancestor Problem
1338
Chapter 190. Level Ancestor Problem
1339
Chapter 190. Level Ancestor Problem
1340
Chapter 190. Level Ancestor Problem
}
return;
}
// LA function to find Lth level ancestor of node x
void LA(vector<vector<int> >& ancstr, vector<int> depth,
int* isNode, int x, int L)
{
int j = 0;
int temp = x;
// to check if node is present in graph or not
if (isNode[x] == 0) {
cout << "Node is not present in graph " << endl;
return;
}
// we change L as depth of node x -
int k = depth[x] - L;
// int q = k;
// in this loop we decrease the value of k by k/2 and
// increment j by 1 after each iteration, and check for set bit
// if we get set bit then we update x with jth ancestor of x
// as k becomes less than or equal to zero means we
// reach to kth level ancestor
while (k > 0) {
// to check if last bit is 1 or not
if (k & 1) {
x = ancstr[x][j];
}
// use of shift operator to make k = k/2
// after every iteration
k = k >> 1;
j++;
}
cout << L << "th level acestor of node "
<< temp << " is = " << x << endl;
return;
}
int main()
{
// n represent number of nodes
int n = 12;
1341
Chapter 190. Level Ancestor Problem
1342
Chapter 190. Level Ancestor Problem
Output:
Source
https://www.geeksforgeeks.org/level-ancestor-problem/
1343
Chapter 191
Level of Each node in a Tree from source node (using BFS) - GeeksforGeeks
BFS(Breadth First Search)is a graph traversal technique where a node and its neighbors
are visited first and then the neighbors of neighbors. In simple terms it traverses level wise
from the source. First it traverses level 1 nodes (direct neighbors of source node) and then
level 2 nodes (neighbors of neighbors of source node) and so on.
Now, suppose if we have to know at which level all the nodes are at (from source node).
Then BFS can be used to determine the level of each node.
Examples:
Input :
Explanation :
1344
Chapter 191. Level of Each node in a Tree from source node (using BFS)
#include <queue>
#include <vector>
using namespace std;
// function to determine level of each node starting
// from x using BFS
void printLevels(vector<int> graph[], int V, int x)
{
// array to store level of each node
int level[V];
bool marked[V];
// create a queue
queue<int> que;
// enqueue element x
que.push(x);
// initialize level of source node to 0
level[x] = 0;
// marked it as visited
marked[x] = true;
// do until queue is empty
while (!que.empty()) {
// get the first element of queue
x = que.front();
// dequeue element
que.pop();
// traverse neighbors of node x
for (int i = 0; i < graph[x].size(); i++) {
// b is neighbor of node x
int b = graph[x][i];
// if b is not marked already
if (!marked[b]) {
// enqueue b in queue
que.push(b);
// level of b is level of x + 1
level[b] = level[x] + 1;
// mark b
1345
Chapter 191. Level of Each node in a Tree from source node (using BFS)
marked[b] = true;
}
}
}
// display all nodes and their levels
cout << "Nodes"
<< " "
<< "Level" << endl;
for (int i = 0; i < V; i++)
cout << " " << i << " --> " << level[i] << endl;
}
// Dirver Code
int main()
{
// adjacency graph for tree
int V = 8;
vector<int> graph[V];
graph[0].push_back(1);
graph[0].push_back(2);
graph[1].push_back(3);
graph[1].push_back(4);
graph[1].push_back(5);
graph[2].push_back(5);
graph[2].push_back(6);
graph[6].push_back(7);
// call levels function with source as 0
printLevels(graph, V, 0);
return 0;
}
Output:
Nodes Level
0 --> 0
1 --> 1
2 --> 1
3 --> 2
4 --> 2
5 --> 2
6 --> 2
7 --> 3
1346
Chapter 191. Level of Each node in a Tree from source node (using BFS)
Source
https://www.geeksforgeeks.org/level-node-tree-source-node-using-bfs/
1347
Chapter 192
Input : n = 6
1 2 3 // Cable length from 1 to 2 (or 2 to 1) is 3
2 3 4
2 6 2
6 4 6
6 5 5
Output: maximum length of cable = 12
1348
Chapter 192. Longest path between any pair of vertices
1349
Chapter 192. Longest path between any pair of vertices
1350
Chapter 192. Longest path between any pair of vertices
Output:
Since there is no negative weight, processing vertices in topological order would always
produce an array of longest paths dist[] such that dist[u] indicates longest path ending at
vertex ‘u’.
The implementation of above approach can be easily adopted from here. The differences
here are, there are no negative weight edges and we need overall longest path (not longest
paths from a source vertex). Finally we return maximum of all values in dist[].
Time Complexity : O(V + E)
This article is contributed by Shashank Mishra ( Gullu ). This article is reviewed by
team GeeksForGeeks. If you have any better approach for this problem then please share.
Source
https://www.geeksforgeeks.org/longest-path-between-any-pair-of-vertices/
1351
Chapter 193
1352
Chapter 193. Longest Path in a Directed Acyclic Graph Set 2
Once we have found all shortest paths from the source vertex, longest paths will be just
negation of shortest paths.
Below is its C++ implementation –
1353
Chapter 193. Longest Path in a Directed Acyclic Graph Set 2
1354
Chapter 193. Longest Path in a Directed Acyclic Graph Set 2
1355
Chapter 193. Longest Path in a Directed Acyclic Graph Set 2
{
Graph g(6);
g.addEdge(0, 1, 5);
g.addEdge(0, 2, 3);
g.addEdge(1, 3, 6);
g.addEdge(1, 2, 2);
g.addEdge(2, 4, 4);
g.addEdge(2, 5, 2);
g.addEdge(2, 3, 7);
g.addEdge(3, 5, 1);
g.addEdge(3, 4, -1);
g.addEdge(4, 5, -2);
int s = 1;
cout << "Following are longest distances from "
<< "source vertex " << s << " \n";
g.longestPath(s);
return 0;
}
Output:
Time Complexity: Time complexity of topological sorting is O(V + E). After finding
topological order, the algorithm process all vertices and for every vertex, it runs a loop for
all adjacent vertices. As total adjacent vertices in a graph is O(E), the inner loop runs O(V
+ E) times. Therefore, overall time complexity of this algorithm is O(V + E).
Source
https://www.geeksforgeeks.org/longest-path-directed-acyclic-graph-set-2/
1356
Chapter 194
m Coloring Problem
Backtracking-5
1357
Chapter 194. m Coloring Problem Backtracking-5
Naive Algorithm
Generate all possible configurations of colors and print a configuration that satisfies the
given constraints.
#include<stdio.h>
// Number of vertices in the graph
#define V 4
void printSolution(int color[]);
/* A utility function to check if the current color assignment
is safe for vertex v i.e. checks whether the edge exists or not
(i.e, graph[v][i]==1). If exist then checks whether the color to
be filled in the new vertex(c is sent in the parameter) is already
used by its adjacent vertices(i-->adj vertices) or not (i.e, color[i]==c) */
bool isSafe (int v, bool graph[V][V], int color[], int c)
{
for (int i = 0; i < V; i++)
if (graph[v][i] && c == color[i])
return false;
return true;
}
/* A recursive utility function to solve m coloring problem */
bool graphColoringUtil(bool graph[V][V], int m, int color[], int v)
1358
Chapter 194. m Coloring Problem Backtracking-5
{
/* base case: If all vertices are assigned a color then
return true */
if (v == V)
return true;
/* Consider this vertex v and try different colors */
for (int c = 1; c <= m; c++)
{
/* Check if assignment of color c to v is fine*/
if (isSafe(v, graph, color, c))
{
color[v] = c;
/* recur to assign colors to rest of the vertices */
if (graphColoringUtil (graph, m, color, v+1) == true)
return true;
/* If assigning color c doesn't lead to a solution
then remove it */
color[v] = 0;
}
}
/* If no color can be assigned to this vertex then return false */
return false;
}
/* This function solves the m Coloring problem using Backtracking.
It mainly uses graphColoringUtil() to solve the problem. It returns
false if the m colors cannot be assigned, otherwise return true and
prints assignments of colors to all vertices. Please note that there
may be more than one solutions, this function prints one of the
feasible solutions.*/
bool graphColoring(bool graph[V][V], int m)
{
// Initialize all color values as 0. This initialization is needed
// correct functioning of isSafe()
int *color = new int[V];
for (int i = 0; i < V; i++)
color[i] = 0;
// Call graphColoringUtil() for vertex 0
if (graphColoringUtil(graph, m, color, 0) == false)
{
printf("Solution does not exist");
return false;
}
1359
Chapter 194. m Coloring Problem Backtracking-5
// Print the solution
printSolution(color);
return true;
}
/* A utility function to print solution */
void printSolution(int color[])
{
printf("Solution Exists:"
" Following are the assigned colors \n");
for (int i = 0; i < V; i++)
printf(" %d ", color[i]);
printf("\n");
}
// driver program to test above function
int main()
{
/* Create following graph and test whether it is 3 colorable
(3)---(2)
| / |
| / |
| / |
(0)---(1)
*/
bool graph[V][V] = {{0, 1, 1, 1},
{1, 0, 1, 0},
{1, 1, 0, 1},
{1, 0, 1, 0},
};
int m = 3; // Number of colors
graphColoring (graph, m);
return 0;
}
Java
1360
Chapter 194. m Coloring Problem Backtracking-5
{
for (int i = 0; i < V; i++)
if (graph[v][i] == 1 && c == color[i])
return false;
return true;
}
/* A recursive utility function to solve m
coloring problem */
boolean graphColoringUtil(int graph[][], int m,
int color[], int v)
{
/* base case: If all vertices are assigned
a color then return true */
if (v == V)
return true;
/* Consider this vertex v and try different
colors */
for (int c = 1; c <= m; c++)
{
/* Check if assignment of color c to v
is fine*/
if (isSafe(v, graph, color, c))
{
color[v] = c;
/* recur to assign colors to rest
of the vertices */
if (graphColoringUtil(graph, m,
color, v + 1))
return true;
/* If assigning color c doesn't lead
to a solution then remove it */
color[v] = 0;
}
}
/* If no color can be assigned to this vertex
then return false */
return false;
}
/* This function solves the m Coloring problem using
Backtracking. It mainly uses graphColoringUtil()
to solve the problem. It returns false if the m
colors cannot be assigned, otherwise return true
1361
Chapter 194. m Coloring Problem Backtracking-5
1362
Chapter 194. m Coloring Problem Backtracking-5
{1, 0, 1, 0},
{1, 1, 0, 1},
{1, 0, 1, 0},
};
int m = 3; // Number of colors
Coloring.graphColoring(graph, m);
}
}
// This code is contributed by Abhishek Shankhadhar
Python
1363
Chapter 194. m Coloring Problem Backtracking-5
Output:
References:
http://en.wikipedia.org/wiki/Graph_coloring
Improved By : SarathChandra1
Source
https://www.geeksforgeeks.org/m-coloring-problem-backtracking-5/
1364
Chapter 195
Input : A = {1, 1, 1, 1}
Output : 4
Possible traversals:
1 -> 3 -> 1
2 -> 4 -> 2
3 -> 1 -> 3
4 -> 2 -> 4
Clearly all the indices are magical
Input : A = {0, 0, 0, 2}
Output : 2
Possible traversals:
1 -> 2 -> 3 -> 4 -> 3...
2 -> 3 -> 4 -> 3...
3 -> 4 -> 3
4 -> 3 ->4
Magical indices = 3, 4
Approach: The problem is of counting number of nodes in all the cycles present in the
graph. Each index represents a single node of the graph. Each node has a single directed
edge as described in the problem statement. This graph has a special property: On starting
1365
Chapter 195. Magical Indices in an array
a traversal from any vertex, a cycle is always detected. This property will be helpful in
reducing the time complexity of the solution.
Read this post on how to detect cycle in a directed graph: Detect Cycle in directed graph
Let the traversal begins from node i. Node i will be called parent node of this traversal and
this parent node will be assigned to all the nodes visited during traversal. While traversing
the graph if we discover a node that is already visited and parent node of that visited node
is same as parent node of the traversal then a new cycle is detected. To count number of
nodes in this cycle, start another dfs from this node until this same node is not visited again.
This procedure is repeated for every node i of the graph. In worst case every node will be
traversed at most 3 times. Hence solution has linear time complexity.
The stepwise algorithm is:
Implementation:
C++
1366
Chapter 195. Magical Indices in an array
1367
Chapter 195. Magical Indices in an array
Java
1368
Chapter 195. Magical Indices in an array
Python3
1369
Chapter 195. Magical Indices in an array
C#
1370
Chapter 195. Magical Indices in an array
class GFG {
// Function to count number of magical
// indices.
static int solve(int []A, int n)
{
int i, cnt = 0, j;
// Array to store parent node of
// traversal.
int []parent = new int[n + 1];
// Array to determine whether current node
// is already counted in the cycle.
int []vis = new int[n + 1];
// Initialize the arrays.
for (i = 0; i < n+1; i++) {
parent[i] = -1;
vis[i] = 0;
}
for (i = 0; i < n; i++) {
j = i;
// Check if current node is already
// traversed or not. If node is not
// traversed yet then parent value
// will be -1.
if (parent[j] == -1) {
// Traverse the graph until an
// already visited node is not
// found.
while (parent[j] == -1) {
parent[j] = i;
j = (j + A[j] + 1) % n;
}
// Check parent value to ensure
// a cycle is present.
if (parent[j] == i) {
// Count number of nodes in
// the cycle.
while (vis[j]==0) {
1371
Chapter 195. Magical Indices in an array
vis[j] = 1;
cnt++;
j = (j + A[j] + 1) % n;
}
}
}
}
return cnt;
}
// Driver code
public static void Main()
{
int []A = { 0, 0, 0, 2 };
int n = A.Length;
Console.WriteLine(solve(A, n));
}
}
// This code is contributed by Manish Shaw
// (manishshaw1)
PHP
<?php
// PHP program to find
// number of magical
// indices in the given
// array.
// Function to count number
// of magical indices.
function solve($A, $n)
{
$i = 0;
$cnt = 0;
$j = 0;
// Array to store parent
// node of traversal.
$parent = array();
// Array to determine
// whether current node
// is already counted
// in the cycle.
$vis = array();
1372
Chapter 195. Magical Indices in an array
// Initialize the arrays.
for ($i = 0; $i < $n + 1; $i++)
{
$parent[$i] = -1;
$vis[$i] = 0;
}
for ($i = 0; $i < $n; $i++)
{
$j = $i;
// Check if current node is
// already traversed or not.
// If node is not traversed
// yet then parent value will
// be -1.
if ($parent[$j] == -1)
{
// Traverse the graph until
// an already visited node
// is not found.
while ($parent[$j] == -1)
{
$parent[$j] = $i;
$j = ($j + $A[$j] + 1) % $n;
}
// Check parent value to ensure
// a cycle is present.
if ($parent[$j] == $i)
{
// Count number of
// nodes in the cycle.
while ($vis[$j] == 0)
{
$vis[$j] = 1;
$cnt++;
$j = ($j + $A[$j] + 1) % $n;
}
}
}
}
return $cnt;
1373
Chapter 195. Magical Indices in an array
}
// Driver code
$A = array( 0, 0, 0, 2 );
$n = count($A);
echo (solve($A, $n));
// This code is contributed by
// Manish Shaw (manishshaw1)
?>
Output :
Source
https://www.geeksforgeeks.org/magical-indices-array/
1374
Chapter 196
We need to understand that an edge connects two vertices. So the sum of degrees of all the
vertices is equal to twice the number of edges.
Therefore,
This is not an integer. As a result we can conclude that our supposition is wrong and such
an arrangement is not possible.
1375
Chapter 196. Mathematics Graph theory practice questions
1376
Chapter 196. Mathematics Graph theory practice questions
Now we consider each square of the grid as a vertex in our graph. There exists a edge between
two vertices in our graph if a valid knight’s move is possible between the corresponding
squares in the graph. For example – If we consider square 1. The reachable squares with
valid knight’s moves are 6 and 8. We can say that vertex 1 is connected to vertices 6 and 8
in our graph.
Similarly we can draw the entire graph as shown below. Clearly vertex 5 can’t be reached
from any of the squares. Hence none of the edges connect to vertex 5.
We use a hollow circle to depict a white knight in our graph and a filled circle to depict a
black knight. Hence the initial state of the graph can be represented as :
1377
Chapter 196. Mathematics Graph theory practice questions
Problem 3: There are 9 line segments drawn in a plane. Is it possible that each line
1378
Chapter 196. Mathematics Graph theory practice questions
Source
https://www.geeksforgeeks.org/graph-theory-practice-questions/
1379
Chapter 197
Each edge is labeled with a capacity, the maximum amount of stuff that it can carry. The
goal is to figure out how much stuff can be pushed from the vertex s(source) to the vertex
t(sink).
maximum flow possible is : 23
Following are different approaches to solve the problem :
E number of edge
1380
Chapter 197. Max Flow Problem Introduction
1) Initialize : max_flow = 0
f(e) = 0 for every edge 'e' in E
3) Return max_flow
Note that the path search just needs to determine whether or not there is an s-t path in the
subgraph of edges e with f(e) < C(e). This is easily done in linear time using BFS or DFS.
There is a path from source (s) to sink(t) [ s -> 1 -> 2 -> t] with maximum flow 3 unit (
path show in blue color )
1381
Chapter 197. Max Flow Problem Introduction
After removing all useless edge from graph it’s look like
For above graph there is no path from source to sink so maximum flow : 3 unit But maximum
flow is 5 unit. to over come form this issue we use residual Graph.
2. Residual Graphs
The idea is to extend the naive greedy algorithm by allowing “undo” operations. For example,
from the point where this algorithm gets stuck in above image, we’d like to route two more
units of flow along the edge (s, 2), then backward along the edge (1, 2), undoing 2 of the 3
units we routed the previous iteration, and finally along the edge (1,t)
1382
Chapter 197. Max Flow Problem Introduction
Source
https://www.geeksforgeeks.org/max-flow-problem-introduction/
1383
Chapter 198
Maximum edges that can be added to DAG so that is remains DAG - GeeksforGeeks
A DAG is given to us, we need to find maximum number of edges that can be added to
this DAG, after which new graph still remain a DAG that means the reformed graph should
have maximal number of edges, adding even single edge will create a cycle in graph.
The Output for above example should be following edges in any order.
4-2, 4-5, 4-3, 5-3, 5-1, 2-0, 2-1, 0-3, 0-1
As shown in above example, we have added all the edges in one direction only to save
ourselves from making a cycle. This is the trick to solve this question. We sort all our nodes
in topological order and create edges from node to all nodes to the right if not there already.
How can we say that, it is not possible to add any more edge? the reason is we have added
all possible edges from left to right and if we want to add more edge we need to make that
from right to left, but adding edge from right to left we surely create a cycle because its
counter part left to right edge is already been added to graph and creating cycle is not what
we needed.
So solution proceeds as follows, we consider the nodes in topological order and if any edge
is not there from left to right, we will create it.
Below is the solution, we have printed all the edges that can be added to given DAG without
making any cycle.
1384
Chapter 198. Maximum edges that can be added to DAG so that is remains DAG
1385
Chapter 198. Maximum edges that can be added to DAG so that is remains DAG
vector<int> Graph::topologicalSort()
{
vector<int> topological;
queue<int> q;
// In starting push all node with indegree 0
for (int i = 0; i < V; i++)
if (indegree[i] == 0)
q.push(i);
while (!q.empty())
{
int t = q.front();
q.pop();
// push the node into topological vector
topological.push_back(t);
// reducing indegree of adjacent vertices
for (list<int>:: iterator j = adj[t].begin();
j != adj[t].end(); j++)
{
indegree[*j]--;
// if indegree becomes 0, just push
// into queue
if (indegree[*j] == 0)
q.push(*j);
}
}
return topological;
}
// The function prints all edges that can be
// added without making any cycle
// It uses recursive topologicalSort()
void Graph::maximumEdgeAddtion()
{
bool *visited = new bool[V];
vector<int> topo = topologicalSort();
// looping for all nodes
for (int i = 0; i < topo.size(); i++)
{
int t = topo[i];
1386
Chapter 198. Maximum edges that can be added to DAG so that is remains DAG
Output:
Source
https://www.geeksforgeeks.org/maximum-edges-can-added-dag-remains-dag/
1387
Chapter 199
Maximum number of edges to be added to a tree so that it stays a Bipartite graph - Geeks-
forGeeks
A tree is always a Bipartite Graphas we can always break into two disjoint sets with alternate
levels. In other words we always color it with two colors such that alternate levels have same
color. The task is to compute the maximum no. of edges that can be added to the tree so
that it remains Bipartite Graph.
Examples:
1388
Chapter 199. Maximum number of edges to be added to a tree so that it stays a Bipartite
graph
1) Do a simple DFS (or BFS) traversal of graph and color it with two colors.
2) While coloring also keep track of counts of nodes colored with the two colors. Let the
two counts be count_color0 and count_color1 .
3) Now we know maximum edges a bipartite graph can have are count_color0 x
count_color1 .
4) We also know tree with n nodes has n-1 edges.
5) So our answer is count_color0 x count_color1 – (n-1).
Below is the CPP implementation :
1389
Chapter 199. Maximum number of edges to be added to a tree so that it stays a Bipartite
graph
// Driver code
int main()
{
int n = 5;
vector<int> adj[n + 1];
adj[1].push_back(2);
adj[1].push_back(3);
adj[2].push_back(4);
adj[3].push_back(5);
cout << findMaxEdges(adj, n);
return 0;
}
Output:
Source
https://www.geeksforgeeks.org/maximum-number-edges-added-tree-stays-bipartite-graph/
1390
Chapter 200
We can solve this problem by depth first search of tree by proceeding as follows, Since tree
is connected and paths are non-intersecting, If we take any pair of such paths there must
be a third path, connecting these two and If we remove an edge from the third path then
tree will be divided into two components — one containing the first path, and the other
containing the second path. This observation suggests us the algorithm: iterate over the
edges; for each edge remove it, find the length of the path in both connected components
and multiply the lengths of these paths. The length of the path in a tree can be found by
modified depth first search where we will call for maximum path at each neighbor and we
will add two maximum lengths returned, which will be the maximum path length at subtree
rooted at current node.
Implementation Details:
Input is a tree, but there is no specified root in it as we have only collection of edges. The
tree is represented as undirected graph. We traverse adjacency list. For every edge, we
find maximum length paths on both sides of it (after removing the edge). We keep track of
maximum product caused by an edge removal.
1391
Chapter 200. Maximum product of two non-intersecting paths in a tree
1392
Chapter 200. Maximum product of two non-intersecting paths in a tree
1393
Chapter 200. Maximum product of two non-intersecting paths in a tree
return 0;
}
Output:
Source
https://www.geeksforgeeks.org/maximum-product-of-two-non-intersecting-paths-in-a-tree/
1394
Chapter 201
Input : 4 4
0 1
1 2
2 3
3 0
Output : 0 disconnected components
Input : 6 5
1 2
2 3
4 5
4 6
5 6
Output : 1 disconnected components
Explanation :
1395
Chapter 201. Minimize the number of weakly connected nodes
Approach : We find a node which helps in traversing maximum nodes in a single walk. To
cover all possible paths, DFS graph traversal technique is used for this.
Do the above steps to traverse the graph. Now, iterate through graph again and check which
nodes are having 0 indegree.
1396
Chapter 201. Minimize the number of weakly connected nodes
// Set of nodes which are traversed
// in each launch of the DFS
set<int> node;
vector<int> Graph[10001];
// Function traversing the graph using DFS
// approach and updating the set of nodes
void dfs(bool visit[], int src)
{
visit[src] = true;
node.insert(src);
int len = Graph[src].size();
for (int i = 0; i < len; i++)
if (!visit[Graph[src][i]])
dfs(visit, Graph[src][i]);
}
// building a undirected graph
void buildGraph(int x[], int y[], int len){
for (int i = 0; i < len; i++)
{
int p = x[i];
int q = y[i];
Graph[p].push_back(q);
Graph[q].push_back(p);
}
}
// computes the minimum number of disconnected
// components when a bi-directed graph is
// converted to a undirected graph
int compute(int n)
{
// Declaring and initializing
// a visited array
bool visit[n + 5];
memset(visit, false, sizeof(visit));
int number_of_nodes = 0;
// We check if each node is
// visited once or not
for (int i = 0; i < n; i++)
{
// We only launch DFS from a
// node iff it is unvisited.
if (!visit[i]) {
1397
Chapter 201. Minimize the number of weakly connected nodes
// Clearing the set of nodes
// on every relaunch of DFS
node.clear();
// relaunching DFS from an
// unvisited node.
dfs(visit, i);
// iterating over the node set to count the
// number of nodes visited after making the
// graph directed and storing it in the
// variable count. If count / 2 == number
// of nodes - 1, then increment count by 1.
int count = 0;
for (auto it = node.begin(); it != node.end(); ++it)
count += Graph[(*it)].size();
count /= 2;
if (count == node.size() - 1)
number_of_nodes++;
}
}
return number_of_nodes;
}
//Driver function
int main()
{
int n = 6,m = 4;
int x[m + 5] = {1, 1, 4, 4};
int y[m+5] = {2, 3, 5, 6};
/*For given x and y above, graph is as below :
1-----2 4------5
| |
| |
| |
3 6
// Note : This code will work for
// connected graph also as :
1-----2
| | \
| | \
| | \
3-----4----5
*/
1398
Chapter 201. Minimize the number of weakly connected nodes
// Building graph in the form of a adjacency list
buildGraph(x, y, n);
cout << compute(n) << " weakly connected nodes";
return 0;
}
Output:
Source
https://www.geeksforgeeks.org/convert-undirected-graph-directed-graph-minimize-disconnected-component/
1399
Chapter 202
Minimum cost path from source node to destination node via an intermediate node - Geeks-
forGeeks
Given an undirected weighted graph. The task is to find the minimum cost of the path from
source node to the destination node via an intermediate node.
Note: If an edge is traveled twice, only once weight is calculated as cost.
1400
Chapter 202. Minimum cost path from source node to destination node via an
intermediate node
Examples:
Approach: Let suppose take a path P1 from Source to intermediate, and a path P2 from
intermediate to destination. There can be some common edges among these 2 paths. Hence,
the optimal path will always have the following form: for any node U, the walk consists
of edges on the shortest path from Source to U, from intermediate to U, and from desti-
nation to U. Hence, if dist(a, b) is the cost of shortest path between node a and b, the
required minimum cost path will be min{ dist(Source, U) + dist(intermediate, U)
+ dist(destination, U) } for all U. The Minimum distance of all nodes from Source, in-
termediate, and destination can be found by doing Dijkstra’s Shortest Path algorithm from
these 3 nodes.
Below is the implementation of the above approach.
1401
Chapter 202. Minimum cost path from source node to destination node via an
intermediate node
1402
Chapter 202. Minimum cost path from source node to destination node via an
intermediate node
vis[x] = true;
for (int i = 0; i < v[x].size(); i++) {
int e = v[x][i].first;
int w = v[x][i].second;
// check if the next vertex
// distance could be minimized
if (dist[x] + w < dist[e]) {
dist[e] = dist[x] + w;
// insert the next vertex
// with the updated distance
s.insert({ dist[e], e });
}
}
}
}
// function to add edges in graph
void add_edge(int s, int t, int weight)
{
v[s].push_back({ t, weight });
v[t].push_back({ s, weight });
}
// function to find the minimum shortest path
int solve(int source, int destination,
int intermediate, int n)
{
int ans = INT_MAX;
dijkstra(source, n);
// store distance from source to
// all other vertices
int dsource[n];
for (int i = 0; i < n; i++)
dsource[i] = dist[i];
dijkstra(destination, n);
// store distance from destination
// to all other vertices
int ddestination[n];
for (int i = 0; i < n; i++)
ddestination[i] = dist[i];
1403
Chapter 202. Minimum cost path from source node to destination node via an
intermediate node
dijkstra(intermediate, n);
// store distance from intermediate
// to all other vertices
int dintermediate[n];
for (int i = 0; i < n; i++)
dintermediate[i] = dist[i];
// find required answer
for (int i = 0; i < n; i++)
ans = min(ans, dsource[i] + ddestination[i]
+ dintermediate[i]);
return ans;
}
// Driver code
int main()
{
int n = 4;
int source = 0, destination = 2, intermediate = 3;
// add edges in graph
add_edge(0, 1, 1);
add_edge(1, 2, 2);
add_edge(1, 3, 3);
// function call for minimum shortest path
cout << solve(source, destination, intermediate, n);
return 0;
}
Output:
Source
https://www.geeksforgeeks.org/minimum-cost-path-from-source-node-to-destination-node-via-an-intermediate-node
1404
Chapter 203
Minimum Cost Path with Left, Right, Bottom and Up moves allowed - GeeksforGeeks
Given a two dimensional grid, each cell of which contains integer cost which represents a
cost to traverse through that cell, we need to find a path from top left cell to bottom right
cell by which total cost incurred is minimum.
Note : It is assumed that negative cost cycles do not exist in input matrix.
This problem is extension of below problem.
Min Cost Path with right and bottom moves allowed.
In previous problem only going right and bottom was allowed but in this problem we are
allowed to go bottom, up, right and left i.e. in all 4 direction.
Examples:
It is not possible to solve this problem using dynamic programming similar to previous
problem because here current state depends not only on right and bottom cells but also on
left and upper cells. We solve this problem using dijkstra’s algorithm. Each cell of grid
represents a vertex and neighbor cells adjacent vertices. We do not make an explicit graph
1405
Chapter 203. Minimum Cost Path with Left, Right, Bottom and Up moves allowed
from these cells instead we will use matrix as it is in our dijkstra’s algorithm.
In below code Dijkstra’ algorithm’s implementation using C++ STL is used. The code
implemented below is changed to cope with matrix represented implicit graph. Please also
see use of dx and dy arrays in below code, these arrays are taken for simplifying the process
of visiting neighbor vertices of each cell.
1406
Chapter 203. Minimum Cost Path with Left, Right, Bottom and Up moves allowed
// initializing distance array by INT_MAX
for (int i = 0; i < row; i++)
for (int j = 0; j < col; j++)
dis[i][j] = INT_MAX;
// direction arrays for simplification of getting
// neighbour
int dx[] = {-1, 0, 1, 0};
int dy[] = {0, 1, 0, -1};
set<cell> st;
// insert (0, 0) cell with 0 distance
st.insert(cell(0, 0, 0));
// initialize distance of (0, 0) with its grid value
dis[0][0] = grid[0][0];
// loop for standard dijkstra's algorithm
while (!st.empty())
{
// get the cell with minimum distance and delete
// it from the set
cell k = *st.begin();
st.erase(st.begin());
// looping through all neighbours
for (int i = 0; i < 4; i++)
{
int x = k.x + dx[i];
int y = k.y + dy[i];
// if not inside boundry, ignore them
if (!isInsideGrid(x, y))
continue;
// If distance from current cell is smaller, then
// update distance of neighbour cell
if (dis[x][y] > dis[k.x][k.y] + grid[x][y])
{
// If cell is already there in set, then
// remove its previous entry
if (dis[x][y] != INT_MAX)
st.erase(st.find(cell(x, y, dis[x][y])));
// update the distance and insert new updated
// cell in set
1407
Chapter 203. Minimum Cost Path with Left, Right, Bottom and Up moves allowed
Output:
327
Source
https://www.geeksforgeeks.org/minimum-cost-path-left-right-bottom-moves-allowed/
1408
Chapter 204
Method: Here we have to connect all the cities by path which will cost us least. The way
to do that is to find out the Minimum Spanning Tree(MST) of the map of the cities(i.e.
1409
Chapter 204. Minimum cost to connect all cities
each city is a node of the graph and all the damaged roads between cities are edges). And
the total cost is the addition of the path edge values in the Minimum Spanning Tree.
Prerequisite: MST Prim’s Algorithm
C++
\
1410
Chapter 204. Minimum cost to connect all cities
1411
Chapter 204. Minimum cost to connect all cities
// Input 1
int n1 = 5;
vector<vector<int>> city1 = {{0, 1, 2, 3, 4},
{1, 0, 5, 0, 7},
{2, 5, 0, 6, 0},
{3, 0, 6, 0, 0},
{4, 7, 0, 0, 0}};
findcost(n1, city1);
// Input 2
int n2 = 6;
vector<vector<int>> city2 = {{0, 1, 1, 100, 0, 0},
{1, 0, 1, 0, 0, 0},
{1, 1, 0, 0, 0, 0},
{100, 0, 0, 0, 2, 2},
{0, 0, 0, 2, 0, 2},
{0, 0, 0, 2, 2, 0}};
findcost(n2, city2);
return 0;
}
Output:
10
106
Complexity: The outer loop(i.e. the loop to add new node to MST) runs n times and in
each iteration of the loop it takes O(n) time to find the minnode and O(n) time to update
the neighboring nodes of u-th node. Hence the overall complexity is O(n2 )
Source
https://www.geeksforgeeks.org/minimum-cost-connect-cities/
1412
Chapter 205
We need to make some observations that we have to make a connected graph with N-1 edges.
As the output will be sum of products of two numbers, we have to minimize the product of
1413
Chapter 205. Minimum cost to connect weighted nodes represented as array
every term in that sum equation. How can we do it? Clearly, choose the minimum element
in the array and connect it with every other. In this way we can reach every other node
from a particular node.
Let, minimum element = a[i], (let it’s index be 0)
Minimum Cost
So, answer is product of minimum element and sum of all the elements except minimum
element.
C++
Java
1414
Chapter 205. Minimum cost to connect weighted nodes represented as array
{
int mn = Integer.MAX_VALUE;
int sum = 0;
for (int i = 0; i < n; i++) {
// To find the minimum element
mn = Math.min(a[i], mn);
// sum of all the elements
sum += a[i];
}
return mn * (sum - mn);
}
// Driver code
public static void main(String[] args)
{
int a[] = { 4, 3, 2, 5 };
int n = a.length;
System.out.println(minimum_cost(a, n));
}
}
// This code is contributed by vt_m.
C#
1415
Chapter 205. Minimum cost to connect weighted nodes represented as array
Output:
24
Source
https://www.geeksforgeeks.org/minimum-cost-connect-weighted-nodes-represented-array/
1416
Chapter 206
We can solve this problem using DFS. we start dfs at any random node of given tree and
at each node we store its distance from starting node assuming all edges as undirected and
we also store number of edges which need to be reversed in the path from starting node
to current node, let’s denote such edges as back edges so back edges are those which point
towards the node in a path. With this dfs, we also calculate total number of edge reversals
in the tree. After this computation, at each node we can calculate ‘number of edge reversal
to reach every other node’ as follows,
Let total number of reversals in tree when some node is chosen as starting node for dfs is R
then if we want to reach every other node from node i we need to reverse all back
edges from path node i to starting node and we also need to reverse all other
back edges other than node i to starting node path. First part will be (distance of
node i from starting node – back edges count at node i) because we want to reverse edges
in path from node i to starting node it will be total edges (i.e. distance) minus back edges
from starting node to node i (i.e. back edge count at node i). The second part will be (total
1417
Chapter 206. Minimum edge reversals to make a root
edge reversal or total back edges of tree R – back edge count of node i). After calculating
this value at each node we will choose minimum of them as our result.
In below code, in the given edge direction weight 0 is added and in reverse direction weight
1 is added which is used to count reversal edges in dfs method.
1418
Chapter 206. Minimum edge reversals to make a root
{
// number of nodes are one more than number of edges
int V = e + 1;
// data structure to store directed tree
vector< pair<int, int> > g[V];
// disRev stores two values - distance and back
// edge count from root node
pair<int, int> disRev[V];
bool visit[V];
int u, v;
for (int i = 0; i < e; i++)
{
u = edges[i][0];
v = edges[i][1];
// add 0 weight in direction of u to v
g[u].push_back(make_pair(v, 0));
// add 1 weight in reverse direction
g[v].push_back(make_pair(u, 1));
}
// initialize all variables
for (int i = 0; i < V; i++)
{
visit[i] = false;
disRev[i].first = disRev[i].second = 0;
}
int root = 0;
// dfs populates disRev data structure and
// store total reverse edge counts
int totalRev = dfs(g, disRev, visit, root);
// UnComment below lines to print each node's
// distance and edge reversal count from root node
/*
for (int i = 0; i < V; i++)
{
cout << i << " : " << disRev[i].first
<< " " << disRev[i].second << endl;
}
*/
1419
Chapter 206. Minimum edge reversals to make a root
int res = INT_MAX;
// loop over all nodes to choose minimum edge reversal
for (int i = 0; i < V; i++)
{
// (reversal in path to i) + (reversal
// in all other tree parts)
int edgesToRev = (totalRev - disRev[i].second) +
(disRev[i].first - disRev[i].second);
// choose minimum among all values
if (edgesToRev < res)
{
res = edgesToRev;
root = i;
}
}
// print the designated root and total
// edge reversal made
cout << root << " " << res << endl;
}
// Driver code to test above methods
int main()
{
int edges[][2] =
{
{0, 1},
{2, 1},
{3, 2},
{3, 4},
{5, 4},
{5, 6},
{7, 6}
};
int e = sizeof(edges) / sizeof(edges[0]);
printMinEdgeReverseForRootNode(edges, e);
return 0;
}
Output:
3 3
1420
Chapter 206. Minimum edge reversals to make a root
Source
https://www.geeksforgeeks.org/minimum-edge-reversals-to-make-a-root/
1421
Chapter 207
Input : n = 3,
m = 2
Edges[] = {{1, 2}, {2, 3}}
Output : 1
For a Euler Circuit to exist in the graph we require that every node should have even degree
because then there exists an edge that can be used to exit the node after entering it.
Now, there can be two case:
1. There is one connected component in the graph
In this case, if all the nodes in the graph is of even degree then we say that the graph already
have a Euler Circuit and we don’t need to add any edge in it. But if there is any node with
odd degree we need to add edges.
There can be even number of odd degree vertices in the graph. This can be easily proved by
the fact that the sum of degrees from the even degrees node and degrees from odd degrees
node should match the total degrees that is always even as every edge contributes two to this
sum. Now, if we pair up random odd degree nodes in the graph and add an edge between
them we can make all nodes to have even degree and thus make an Euler Circuit exist.
2. There are disconnected components in the graph
We first mark component as odd and even. Odd components are those which have at least
1422
Chapter 207. Minimum edges required to add to make Euler Circuit
one odd degree node in them. Take all the even components and select a random vertex from
every component and line them up linearly. Now we add an edge between adjacent vertices.
So we have connected the even components and made an equivalent odd components that
has two nodes with odd degree.
Now to deal with odd components i.e components with at least one odd degree node. We
can connect all these odd components using edges whose number is equal to the number of
disconnected components. This can be done by placing the components in the cyclic order
and picking two odd degree nodes from every component and using these to connect to the
components on either side. Now we have a single connected component for which we have
discussed.
Below is C++ implementation of this approach:
1423
Chapter 207. Minimum edges required to add to make Euler Circuit
for (int i = 0; i < m; i++)
{
g[s[i]].push_back(d[i]);
g[d[i]].push_back(s[i]);
deg[s[i]]++;
deg[d[i]]++;
}
// 'ans' is result and 'comp' is component id
int ans = 0, comp = 0;
for (int i = 1; i <= n; i++)
{
if (vis[i]==0)
{
comp++;
dfs(g, vis, odd, deg, comp, i);
// Checking if connected component
// is odd.
if (odd[comp] == 0)
e.push_back(comp);
// Checking if connected component
// is even.
else
o.push_back(comp);
}
}
// If whole graph is a single connected
// component with even degree.
if (o.size() == 0 && e.size() == 1)
return 0;
// If all connected component is even
if (o.size() == 0)
return e.size();
// If graph have atleast one even connected
// component
if (e.size() != 0)
ans += e.size();
// For all the odd connected component.
for (int i : o)
ans += odd[i]/2;
1424
Chapter 207. Minimum edges required to add to make Euler Circuit
return ans;
}
// Driven Program
int main()
{
int n = 3, m = 2;
int source[] = { 1, 2 };
int destination[] = { 2, 3 };
cout << minEdge(n, m, source, destination) << endl;
return 0;
}
Output:
Source
https://www.geeksforgeeks.org/minimum-edges-required-to-add-to-make-euler-circuit/
1425
Chapter 208
This problem can be solved assuming a different version of the given graph. In this version
we make a reverse edge corresponding to every edge and we assign that a weight 1 and
assign a weight 0 to original edge. After this modification above graph looks something like
below,
1426
Chapter 208. Minimum edges to reverse to make path from a source to a destination
Now we can see that we have modified the graph in such a way that, if we move towards
original edge, no cost is incurred, but if we move toward reverse edge 1 cost is added. So if
we apply Dijkstra’s shortest path on this modified graph from given source, then that will
give us minimum cost to reach from source to destination i.e. minimum edge reversal from
source to destination.
Below is the code based on above concept.
1427
Chapter 208. Minimum edges to reverse to make path from a source to a destination
// In a weighted graph, we need to store vertex
// and weight pair for every edge
list< pair<int, int> > *adj;
public:
Graph(int V); // Constructor
// function to add an edge to graph
void addEdge(int u, int v, int w);
// returns shortest path from s
vector<int> shortestPath(int s);
};
// Allocates memory for adjacency list
Graph::Graph(int V)
{
this->V = V;
adj = new list< pair<int, int> >[V];
}
// method adds a directed edge from u to v with weight w
void Graph::addEdge(int u, int v, int w)
{
adj[u].push_back(make_pair(v, w));
}
// Prints shortest paths from src to all other vertices
vector<int> Graph::shortestPath(int src)
{
// Create a set to store vertices that are being
// prerocessed
set< pair<int, int> > setds;
// Create a vector for distances and initialize all
// distances as infinite (INF)
vector<int> dist(V, INF);
// Insert source itself in Set and initialize its
// distance as 0.
setds.insert(make_pair(0, src));
dist[src] = 0;
/* Looping till all shortest distance are finalized
then setds will become empty */
while (!setds.empty())
{
1428
Chapter 208. Minimum edges to reverse to make path from a source to a destination
1429
Chapter 208. Minimum edges to reverse to make path from a source to a destination
{
Graph g(V);
for (int i = 0; i < E; i++)
{
// original edge : weight 0
g.addEdge(edge[i][0], edge[i][1], 0);
// reverse edge : weight 1
g.addEdge(edge[i][1], edge[i][0], 1);
}
return g;
}
// Method returns minimum number of edges to be
// reversed to reach from src to dest
int getMinEdgeReversal(int edge[][2], int E, int V,
int src, int dest)
{
// get modified graph with edge weight
Graph g = modelGraphWithEdgeWeight(edge, E, V);
// get shortes path vector
vector<int> dist = g.shortestPath(src);
// If distance of destination is still INF,
// not possible
if (dist[dest] == INF)
return -1;
else
return dist[dest];
}
// Driver code to test above method
int main()
{
int V = 7;
int edge[][2] = {{0, 1}, {2, 1}, {2, 3}, {5, 1},
{4, 5}, {6, 4}, {6, 3}};
int E = sizeof(edge) / sizeof(edge[0]);
int minEdgeToReverse =
getMinEdgeReversal(edge, E, V, 0, 6);
if (minEdgeToReverse != -1)
cout << minEdgeToReverse << endl;
else
cout << "Not possible" << endl;
return 0
}
1430
Chapter 208. Minimum edges to reverse to make path from a source to a destination
Output:
Source
https://www.geeksforgeeks.org/minimum-edges-reverse-make-path-source-destination/
1431
Chapter 209
Minimum initial vertices to traverse whole matrix with given conditions - GeeksforGeeks
We are given a matrix that contains different values in its each cell. Our aim is to find the
minimal set of positions in the matrix such that entire matrix can be traversed starting from
the positions in the set.
We can traverse the matrix under below conditions:
• We can move only to those neighbors that contain value less than or to equal to the
current cell’s value. A neighbor of cell is defined as the cell that shares a side with the
given cell.
Examples:
Input : 1 2 3
2 3 1
1 1 1
Output : 1 1
0 2
If we start from 1, 1 we can cover 6
vertices in the order 1, 1 -> 1, 0 -> 2, 0
-> 2, 1 -> 2, 2 -> 1, 2. We cannot cover
the entire matrix with this vertex. Remaining
vertices can be covered 0, 2 -> 0, 1 -> 0, 0.
Input : 3 3
1 1
1432
Chapter 209. Minimum initial vertices to traverse whole matrix with given conditions
Output : 0 1
If we start from 0, 1, we can traverse
the entire matrix from this single vertex
in this order 0, 0 -> 0, 1 -> 1, 1 -> 1, 0.
Traversing the matrix in this order
satisfies all the conditions stated above.
From the above examples, we can easily identify that in order to use minimum number of
positions we have to start from the positions having highest cell value. Therefore we pick the
positions that contain the highest value in the matrix. We take the vertices having highest
value in separate array. We perform DFS on every vertex starting from the highest value.
If we encounter any unvisited vertex during dfs then we have to include this vertex in our
set. When all the cells have been processed then the set contains the required vertices.
How does this work?
We need to visit all vertices and to reach largest values we must start with them. If two
largest values are not adjacent, then both of them must be picked. If two largest values are
adjacent, then any of them can be picked as moving to equal value neighbors is allowed.
1433
Chapter 209. Minimum initial vertices to traverse whole matrix with given conditions
!visit[n][m + 1])
dfs(n, m + 1, visit, adj, N, M);
// If above neighbor is valid and has
// value less than or equal to current
// cell's value
if (n - 1 >= 0 &&
adj[n][m] >= adj[n - 1][m] &&
!visit[n - 1][m])
dfs(n - 1, m, visit, adj, N, M);
// If left neighbor is valid and has
// value less than or equal to current
// cell's value
if (m - 1 >= 0 &&
adj[n][m] >= adj[n][m - 1] &&
!visit[n][m - 1])
dfs(n, m - 1, visit, adj, N, M);
}
void printMinSources(int adj[][MAX], int N, int M)
{
// Storing the cell value and cell indices
// in a vector.
vector<pair<long int, pair<int, int> > > x;
for (int i = 0; i < N; i++)
for (int j = 0; j < M; j++)
x.push_back(make_pair(adj[i][j],
make_pair(i, j)));
// Sorting the newly created array according
// to cell values
sort(x.begin(), x.end());
// Create a visited array for DFS and
// initialize it as false.
bool visit[N][MAX];
memset(visit, false, sizeof(visit));
// Applying dfs for each vertex with
// highest value
for (int i = x.size()-1; i >=0 ; i--)
{
// If the given vertex is not visited
// then include it in the set
if (!visit[x[i].second.first][x[i].second.second])
{
1434
Chapter 209. Minimum initial vertices to traverse whole matrix with given conditions
Output:
0 1
Source
https://www.geeksforgeeks.org/minimum-initial-vertices-traverse-whole-matrix-given-conditions/
1435
Chapter 210
Output : 2
Explanation: (1, 2) and (2, 5) are the only
edges resulting into shortest path between 1
and 5.
The idea is to perform BFS from one of given input vertex(u). At the time of BFS maintain
an array of distance[n] and initialize it to zero for all vertices. Now, suppose during BFS,
vertex x is popped from queue and we are pushing all adjacent non-visited vertices(i) back
into queue at the same time we should update distance[i] = distance[x] + 1;.
Finally distance[v] gives the minimum number of edges between u and v.
Algorithm:
1436
Chapter 210. Minimum number of edges between two vertices of a Graph
// Initialize distances as 0
int distance[n] = {0};
// queue to do BFS.
queue Q;
distance[u] = 0;
Q.push(u);
visited[u] = true;
while (!Q.empty())
{
int x = Q.front();
Q.pop();
C++
1437
Chapter 210. Minimum number of edges between two vertices of a Graph
queue <int> Q;
distance[u] = 0;
Q.push(u);
visited[u] = true;
while (!Q.empty())
{
int x = Q.front();
Q.pop();
for (int i=0; i<edges[x].size(); i++)
{
if (visited[edges[x][i]])
continue;
// update distance for i
distance[edges[x][i]] = distance[x] + 1;
Q.push(edges[x][i]);
visited[edges[x][i]] = 1;
}
}
return distance[v];
}
// function for addition of edge
void addEdge(vector <int> edges[], int u, int v)
{
edges[u].push_back(v);
edges[v].push_back(u);
}
// Driver function
int main()
{
// To store adjacency list of graph
int n = 9;
vector <int> edges[9];
addEdge(edges, 0, 1);
addEdge(edges, 0, 7);
addEdge(edges, 1, 7);
addEdge(edges, 1, 2);
addEdge(edges, 2, 3);
addEdge(edges, 2, 5);
addEdge(edges, 2, 8);
addEdge(edges, 3, 4);
addEdge(edges, 3, 5);
addEdge(edges, 4, 5);
addEdge(edges, 5, 6);
1438
Chapter 210. Minimum number of edges between two vertices of a Graph
addEdge(edges, 6, 7);
addEdge(edges, 7, 8);
int u = 0;
int v = 5;
cout << minEdgeBFS(edges, u, v, n);
return 0;
}
Java
1439
Chapter 210. Minimum number of edges between two vertices of a Graph
Q.poll();
for (int i=0; i<edges[x].size(); i++)
{
if (visited.elementAt(edges[x].get(i)))
continue;
// update distance for i
distance.setElementAt(distance.get(x) + 1,edges[x].get(i));
Q.add(edges[x].get(i));
visited.setElementAt(true,edges[x].get(i));
}
}
return distance.get(v);
}
// method for addition of edge
static void addEdge(Vector <Integer> edges[], int u, int v)
{
edges[u].add(v);
edges[v].add(u);
}
// Driver method
public static void main(String args[])
{
// To store adjacency list of graph
int n = 9;
Vector <Integer> edges[] = new Vector[9];
for (int i = 0; i < edges.length; i++) {
edges[i] = new Vector<>();
}
addEdge(edges, 0, 1);
addEdge(edges, 0, 7);
addEdge(edges, 1, 7);
addEdge(edges, 1, 2);
addEdge(edges, 2, 3);
addEdge(edges, 2, 5);
addEdge(edges, 2, 8);
addEdge(edges, 3, 4);
addEdge(edges, 3, 5);
addEdge(edges, 4, 5);
addEdge(edges, 5, 6);
addEdge(edges, 6, 7);
addEdge(edges, 7, 8);
int u = 0;
1440
Chapter 210. Minimum number of edges between two vertices of a Graph
int v = 5;
System.out.println(minEdgeBFS(edges, u, v, n));
}
}
// This code is contributed by Gaurav Miglani
Output:
Source
https://www.geeksforgeeks.org/minimum-number-of-edges-between-two-vertices-of-a-graph/
1441
Chapter 211
1. Multiply number by 2.
2. Subtract 1 from the number.
The task is to find out minimum number of operation required to convert number x into y
using only above two operations. We can apply these operations any number of times.
Constraints:
1 <= x, y <= 10000
Example:
Input : x = 4, y = 7
Output : 2
We can transform x into y using following
two operations.
1. 4*2 = 8
2. 8-1 = 7
Input : x = 2, y = 5
Output : 4
We can transform x into y using following
four operations.
1442
Chapter 211. Minimum number of operation required to convert number x into y
1. 2*2 = 4
2. 4-1 = 3
3. 3*2 = 6
4. 6-1 = 5
Answer = 4
Note that other sequences of two operations
would take more operations.
The idea is to use BFS for this. We run a BFS and create nodes by multiplying with 2 and
subtracting by 1, thus we can obtain all possible numbers reachable from starting number.
Important Points :
1) When we subtract 1 from a number and if it becomes < 0 i.e. Negative then there is no
reason to create next node from it (As per input constraints, numbers x and y are positive).
2) Also, if we have already created a number then there is no reason to create it again. i.e.
we maintain a visited array.
C++
1443
Chapter 211. Minimum number of operation required to convert number x into y
{
// Remove an item from queue
node t = q.front();
q.pop();
// If the removed item is target
// number y, return its level
if (t.val == y)
return t.level;
// Mark dequeued number as visited
visit.insert(t.val);
// If we can reach y in one more step
if (t.val*2 == y || t.val-1 == y)
return t.level+1;
// Insert children of t if not visited
// already
if (visit.find(t.val*2) == visit.end())
{
n.val = t.val*2;
n.level = t.level+1;
q.push(n);
}
if (t.val-1>=0 && visit.find(t.val-1) == visit.end())
{
n.val = t.val-1;
n.level = t.level+1;
q.push(n);
}
}
}
// Driver code
int main()
{
int x = 4, y = 7;
cout << minOperations(x, y);
return 0;
}
Java
1444
Chapter 211. Minimum number of operation required to convert number x into y
1445
Chapter 211. Minimum number of operation required to convert number x into y
{
GFG nodeMul = new GFG(mul, temp.steps + 1);
queue.offer(nodeMul);
}
if (sub > 0 && sub < 1000)
{
GFG nodeSub = new GFG(sub, temp.steps + 1);
queue.offer(nodeSub);
}
}
return -1;
}
// Driver code
public static void main(String[] args)
{
// int x = 2, y = 5;
int x = 4, y = 7;
GFG src = new GFG(x, y);
System.out.println(minOperations(x, y));
}
}
// This code is contributed by Rahul
Output :
Improved By : rahulpopat
Source
https://www.geeksforgeeks.org/minimum-number-operation-required-convert-number-x-y/
1446
Chapter 212
Input : {4, 3, 2, 1}
Output : 2
Explanation : Swap index 0 with 3 and 1 with 2 to
form the sorted array {1, 2, 3, 4}.
Input : {1, 5, 4, 3, 2}
Output : 2
This can be easily done by visualizing the problem as a graph. We will have n nodes and
an edge directed from node i to node j if the element at i’th index must be present at j’th
index in the sorted array.
The graph will now contain many non-intersecting cycles. Now a cycle with 2 nodes will
only require 1 swap to reach the correct ordering, similarly a cycle with 3 nodes will only
require 2 swap to do so.
1447
Chapter 212. Minimum number of swaps required to sort an array
Hence,
k
ans = Σi = 1 (cycle_size – 1)
where k is the number of cycles
Below is the C++ implementation of the idea.
C++
1448
Chapter 212. Minimum number of swaps required to sort an array
Java
1449
Chapter 212. Minimum number of swaps required to sort an array
// Create two arrays and use as pairs where first
// array is element and second array
// is position of first element
ArrayList <Pair <Integer, Integer> > arrpos =
new ArrayList <Pair <Integer, Integer> > ();
for (int i = 0; i < n; i++)
arrpos.add(new Pair <Integer, Integer> (arr[i], i));
// Sort the array by array element values to
// get right position of every element as the
// elements of second array.
arrpos.sort(new Comparator<Pair<Integer, Integer>>()
{
@Override
public int compare(Pair<Integer, Integer> o1,
Pair<Integer, Integer> o2)
{
if (o1.getKey() > o2.getKey())
return -1;
// We can change this to make it then look at the
// words alphabetical order
else if (o1.getKey().equals(o2.getKey()))
return 0;
else
return 1;
}
});
// To keep track of visited elements. Initialize
// all elements as not visited or false.
Boolean[] vis = new Boolean[n];
Arrays.fill(vis, false);
// Initialize result
int ans = 0;
// Traverse array elements
for (int i = 0; i < n; i++)
{
// already swapped and corrected or
// already present at correct pos
if (vis[i] || arrpos.get(i).getValue() == i)
continue;
// find out the number of node in
1450
Chapter 212. Minimum number of swaps required to sort an array
[/sourcecode]
Python3
1451
Chapter 212. Minimum number of swaps required to sort an array
1452
Chapter 212. Minimum number of swaps required to sort an array
# Driver Code
arr = [1, 5, 4, 3, 2]
print(minSwaps(arr))
# This code is contributed
# by Dharan Aditya
Output:
Source
https://www.geeksforgeeks.org/minimum-number-swaps-required-sort-array/
1453
Chapter 213
This problem can be solved using standard minimum spanning tree algorithms like krushkal
and prim’s algorithm, but we need to modify our graph to use these algorithms. Minimum
spanning tree algorithms tries to minimize total sum of weights, here we need to minimize
total product of weights. We can use property of logarithms to overcome this problem.
As we know,
log(w1* w2 * w3 * …. * wN) =
log(w1) + log(w2) + log(w3) ….. + log(wN)
1454
Chapter 213. Minimum Product Spanning Tree
We can replace each weight of graph by its log value, then we apply any minimum spanning
tree algorithm which will try to minimize sum of log(wi) which in-turn minimizes weight
product.
For example graph, steps are shown in below diagram,
In below code first we have constructed the log graph from given input graph, then that
graph is given as input to prim’s MST algorithm, which will minimize the total sum of
weights of tree. Since weight of modified graph are logarithms of actual input graph, we
actually minimize the product of weights of spanning tree.
1455
Chapter 213. Minimum Product Spanning Tree
int minProduct = 1;
for (int i = 1; i < V; i++)
{
printf("%d - %d %d \n",
parent[i], i, graph[i][parent[i]]);
minProduct *= graph[i][parent[i]];
}
printf("Minimum Obtainable product is %d\n",
minProduct);
}
// Function to construct and print MST for a graph
// represented using adjacency matrix representation
// inputGraph is sent for printing actual edges and
// logGraph is sent for actual MST operations
void primMST(int inputGraph[V][V], double logGraph[V][V])
{
int parent[V]; // Array to store constructed MST
int key[V]; // Key values used to pick minimum
// weight edge in cut
bool mstSet[V]; // To represent set of vertices not
// yet included in MST
// Initialize all keys as INFINITE
for (int i = 0; i < V; i++)
key[i] = INT_MAX, mstSet[i] = false;
// Always include first 1st vertex in MST.
key[0] = 0; // Make key 0 so that this vertex is
// picked as first vertex
parent[0] = -1; // First node is always root of MST
// The MST will have V vertices
for (int count = 0; count < V-1; count++)
{
// Pick the minimum key vertex from the set of
// vertices not yet included in MST
int u = minKey(key, mstSet);
// Add the picked vertex to the MST Set
mstSet[u] = true;
// Update key value and parent index of the
// adjacent vertices of the picked vertex.
// Consider only those vertices which are not yet
// included in MST
for (int v = 0; v < V; v++)
1456
Chapter 213. Minimum Product Spanning Tree
// logGraph[u][v] is non zero only for
// adjacent vertices of m mstSet[v] is false
// for vertices not yet included in MST
// Update the key only if logGraph[u][v] is
// smaller than key[v]
if (logGraph[u][v] > 0 &&
mstSet[v] == false &&
logGraph[u][v] < key[v])
parent[v] = u, key[v] = logGraph[u][v];
}
// print the constructed MST
printMST(parent, V, inputGraph);
}
// Method to get minimum product spanning tree
void minimumProductMST(int graph[V][V])
{
double logGraph[V][V];
// Constructing logGraph from original graph
for (int i = 0; i < V; i++)
{
for (int j = 0; j < V; j++)
{
if (graph[i][j] > 0)
logGraph[i][j] = log(graph[i][j]);
else
logGraph[i][j] = 0;
}
}
// Applyting standard Prim's MST algorithm on
// Log graph.
primMST(graph, logGraph);
}
// driver program to test above function
int main()
{
/* Let us create the following graph
2 3
(0)--(1)--(2)
| / \ |
6| 8/ \5 |7
| / \ |
1457
Chapter 213. Minimum Product Spanning Tree
(3)-------(4)
9 */
int graph[V][V] = {{0, 2, 0, 6, 0},
{2, 0, 3, 8, 5},
{0, 3, 0, 0, 7},
{6, 8, 0, 0, 9},
{0, 5, 7, 9, 0},
};
// Print the solution
minimumProductMST(graph);
return 0;
}
Output:
Edge Weight
0 - 1 2
1 - 2 3
0 - 3 6
1 - 4 5
Minimum Obtainable product is 180
Source
https://www.geeksforgeeks.org/minimum-product-spanning-tree/
1458
Chapter 214
1459
Chapter 214. Minimum steps to reach a destination
of steps INT_MAX, so that when i take the minimum of both possibilities, this one gets
eliminated.
If we don’t use this last step, the program enters into an INFINITE recursion and gives
RUN TIME ERROR.
Below is the implementation of above idea. Note that the solution only counts steps.
C++
1460
Chapter 214. Minimum steps to reach a destination
Java
1461
Chapter 214. Minimum steps to reach a destination
// This code is contributed by Prerna Saini
Python3
1462
Chapter 214. Minimum steps to reach a destination
C#
1463
Chapter 214. Minimum steps to reach a destination
PHP
<?php
// PHP program to count number
// of steps to reach a point
// Function to count number
// of steps required to reach
// a destination
// source -> source vertex
// step -> value of last step taken
// dest -> destination vertex
function steps($source, $step, $dest)
{
// base cases
if (abs($source) > ($dest))
return PHP_INT_MAX;
if ($source == $dest)
return $step;
// at each point we
// can go either way
// if we go on positive side
$pos = steps($source + $step + 1,
$step + 1, $dest);
// if we go on negative side
$neg = steps($source - $step - 1,
$step + 1, $dest);
// minimum of both cases
return min($pos, $neg);
}
// Driver code
$dest = 11;
echo "No. of steps required to reach ",
$dest, " is ", steps(0, 0, $dest);
// This code is contributed by aj_36
?>
Output :
1464
Chapter 214. Minimum steps to reach a destination
Source
https://www.geeksforgeeks.org/minimum-steps-to-reach-a-destination/
1465
Chapter 215
This problem can be solved using BFS. We can consider the given array as unweighted graph
where every vertex has two edges to next and previous array elements and more edges to
array elements with same values. Now for fast processing of third type of edges, we keep
10 vectors which store all indices where digits 0 to 9 are present. In above example, vector
1466
Chapter 215. Minimum steps to reach end of array under constraints
corresponding to 0 will store [0, 12], 2 indices where 0 has occurred in given array.
Another Boolean array is used, so that we don’t visit same index more than once. As we
are using BFS and BFS proceeds level by level, optimal minimum steps are guaranteed.
1467
Chapter 215. Minimum steps to reach end of array under constraints
// Find value of dequeued index
int d = arr[idx];
// looping for all indices with value as d.
for (int i = 0; i<digit[d].size(); i++)
{
int nextidx = digit[d][i];
if (!visit[nextidx])
{
visit[nextidx] = true;
q.push(nextidx);
// update the distance of this nextidx
distance[nextidx] = distance[idx] + 1;
}
}
// clear all indices for digit d, because all
// of them are processed
digit[d].clear();
// checking condition for previous index
if (idx-1 >= 0 && !visit[idx - 1])
{
visit[idx - 1] = true;
q.push(idx - 1);
distance[idx - 1] = distance[idx] + 1;
}
// checking condition for next index
if (idx + 1 < N && !visit[idx + 1])
{
visit[idx + 1] = true;
q.push(idx + 1);
distance[idx + 1] = distance[idx] + 1;
}
}
// N-1th position has the final result
return distance[N - 1];
}
// driver code to test above methods
int main()
{
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 5,
4, 3, 6, 0, 1, 2, 3, 4, 5, 7};
1468
Chapter 215. Minimum steps to reach end of array under constraints
Output:
Source
https://www.geeksforgeeks.org/minimum-steps-reach-end-array-constraints/
1469
Chapter 216
This problem can be seen as shortest path in unweighted graph. Therefore we use BFS
to solve this problem. We try all 8 possible positions where a Knight can reach from its
position. If reachable position is not already visited and is inside the board, we push this
state into queue with distance 1 more than its parent state. Finally we return distance of
target position, when it gets pop out from queue.
Below code implements BFS for searching through cells, where each cell contains its coor-
dinate and distance from starting node. In worst case, below code visits all cells of board,
making worst-case time complexity as O(N^2)
1470
Chapter 216. Minimum steps to reach target by a Knight Set 1
struct cell
{
int x, y;
int dis;
cell() {}
cell(int x, int y, int dis) : x(x), y(y), dis(dis) {}
};
// Utility method returns true if (x, y) lies
// inside Board
bool isInside(int x, int y, int N)
{
if (x >= 1 && x <= N && y >= 1 && y <= N)
return true;
return false;
}
// Method returns minimum step to reach target position
int minStepToReachTarget(int knightPos[], int targetPos[],
int N)
{
// x and y direction, where a knight can move
int dx[] = {-2, -1, 1, 2, -2, -1, 1, 2};
int dy[] = {-1, -2, -2, -1, 1, 2, 2, 1};
// queue for storing states of knight in board
queue<cell> q;
// push starting position of knight with 0 distance
q.push(cell(knightPos[0], knightPos[1], 0));
cell t;
int x, y;
bool visit[N + 1][N + 1];
// make all cell unvisited
for (int i = 1; i <= N; i++)
for (int j = 1; j <= N; j++)
visit[i][j] = false;
// visit starting state
visit[knightPos[0]][knightPos[1]] = true;
// loop untill we have one element in queue
while (!q.empty())
{
t = q.front();
q.pop();
1471
Chapter 216. Minimum steps to reach target by a Knight Set 1
// if current cell is equal to target cell,
// return its distance
if (t.x == targetPos[0] && t.y == targetPos[1])
return t.dis;
// loop for all reachable states
for (int i = 0; i < 8; i++)
{
x = t.x + dx[i];
y = t.y + dy[i];
// If reachable state is not yet visited and
// inside board, push that state into queue
if (isInside(x, y, N) && !visit[x][y]) {
visit[x][y] = true;
q.push(cell(x, y, t.dis + 1));
}
}
}
}
// Driver code to test above methods
int main()
{
int N = 30;
int knightPos[] = {1, 1};
int targetPos[] = {30, 30};
cout << minStepToReachTarget(knightPos, targetPos, N);
return 0;
}
Output:
20
Source
https://www.geeksforgeeks.org/minimum-steps-reach-target-knight/
1472
Chapter 217
• We are given another integer ‘steps’, times which we need to perform this operation.
• Another constraint is that we can’t put same weight consecutively i.e. if weight w
is taken then in next step while putting the weight on opposite pan we can’t take w
again.
1. We traverse among various DFS states for the solution where each DFS state will
correspond to actual difference value between left and right pans and current step
count.
1473
Chapter 217. Move weighting scale alternate under given constraints
2. Instead of storing weights of both pans, we just store the difference residue value and
each time chosen weight value should be greater than this difference and shouldn’t be
equal to previously chosen value of weight.
3. If it is, then we call the DFS method recursively with new difference value and one
more step.
1474
Chapter 217. Move weighting scale alternate under given constraints
{
int wt[steps];
// call dfs with current residue as 0 and current
// steps as 0
if (dfs(0, 0, wt, arr, N, steps))
{
for (int i = 0; i < steps; i++)
cout << wt[i] << " ";
cout << endl;
}
else
cout << "Not possible\n";
}
// Driver code to test above methods
int main()
{
int arr[] = {2, 3, 5, 6};
int N = sizeof(arr) / sizeof(int);
int steps = 10;
printWeightsOnScale(arr, N, steps);
return 0;
}
Output:
2 3 2 3 5 6 5 3 2 3
Source
https://www.geeksforgeeks.org/move-weighting-scale-alternate-given-constraints/
1475
Chapter 218
Input :
Number of Vertices = 6
Number of Edges = 9
Towns with Police Station : 1, 5
Edges:
1 2
1 6
2 6
2 3
3 6
5 4
6 5
3 4
5 3
Output :
1 0
2 1
3 1
4 1
5 0
1476
Chapter 218. Multi Source Shortest Path in Unweighted Graph
6 1
Naive Approach: We can loop through the vertices and from each vertex run a BFS to
find the closest town with police station from that vertex. This will take O(V.E).
Naive approach implementation using BFS from each vertex:
1477
Chapter 218. Multi Source Shortest Path in Unweighted Graph
1478
Chapter 218. Multi Source Shortest Path in Unweighted Graph
int main()
{ // Number of vertices
int n = 6;
vector<int> graph[n + 1];
// Edges
addEdge(graph, 1, 2);
addEdge(graph, 1, 6);
addEdge(graph, 2, 6);
addEdge(graph, 2, 3);
addEdge(graph, 3, 6);
addEdge(graph, 5, 4);
addEdge(graph, 6, 5);
addEdge(graph, 3, 4);
addEdge(graph, 5, 3);
// Sources
int sources[] = { 1, 5 };
int S = sizeof(sources) / sizeof(sources[0]);
nearestTown(graph, n, sources, S);
return 0;
}
Output:
1 0
2 1
3 1
4 1
5 0
6 1
1479
Chapter 218. Multi Source Shortest Path in Unweighted Graph
On each step, we will go to the vertex with minimum distance(d) from source, i.e, the first
element of the set (the source itself in the first step with distance = 0). We go through all
it’s adjacent vertices and if the distance of any vertex is > d + 1 we replace its entry in the
set with the new distance. Then we remove the current vertex from the set. We continue
this until the set is empty.
The idea is there cannot be a shorter path to the vertex at the front of the set than the
current one since any other path will be a sum of a longer path (>= it’s length) and a
non-negative path length (unless we are considering negative edges).
Since all the sources have a distance = 0, in the beginning, the adjacent non-source vertices
will get a distance = 1. All vertices will get distance = distance from their nearest source.
Implementation of Efficient Approach:
1480
Chapter 218. Multi Source Shortest Path in Unweighted Graph
1481
Chapter 218. Multi Source Shortest Path in Unweighted Graph
multiSourceBFSUtil(graph, start);
// Printing the distances
for (int i = 1; i <= n; i++)
cout << i << " " << dist[i] << endl;
}
void addEdge(vector<int> graph[], int u, int v)
{
graph[u].push_back(v);
graph[v].push_back(u);
}
// Driver Code
int main()
{
// Number of vertices
int n = 6;
vector<int> graph[n + 1];
// Edges
addEdge(graph, 1, 2);
addEdge(graph, 1, 6);
addEdge(graph, 2, 6);
addEdge(graph, 2, 3);
addEdge(graph, 3, 6);
addEdge(graph, 5, 4);
addEdge(graph, 6, 5);
addEdge(graph, 3, 4);
addEdge(graph, 5, 3);
// Sources
int sources[] = { 1, 5 };
int S = sizeof(sources) / sizeof(sources[0]);
multiSourceBFS(graph, n, sources, S);
return 0;
}
Output:
1 0
2 1
1482
Chapter 218. Multi Source Shortest Path in Unweighted Graph
3 1
4 1
5 0
6 1
Source
https://www.geeksforgeeks.org/multi-source-shortest-path-in-unweighted-graph/
1483
Chapter 219
1484
Chapter 219. Multistage Graph (Shortest Path)
• 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 give 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.
We define the notation :- M(x, y) as the minimum cost to T(target node) from Stage x,
Node y.
// From 0, we can go to 1 or 2 or 3 to
// reach 7.
M(1, 0) = min(1 + M(2, 1),
2 + M(2, 2),
5 + M(2, 3))
This means that our problem of 0 —> 7 is now sub-divided into 3 sub-problems :-
M(1, 0)
/ | \
1485
Chapter 219. Multistage Graph (Shortest Path)
/ | \
M(2, 1) M(2, 2) M(2, 3)
/ \ / \ / \
M(3, 4) M(3, 5) M(3, 4) M(3, 5) M(3, 6) M(3, 6)
. . . . . .
. . . . . .
. . . . . .
So, here we have drawn a very small part of the Recursion Tree and we can already see
Overlapping Sub-Problems. We can largely reduce the number of M(x, y) evaluations using
Dynamic Programming.
Implementation details:
The below implementation assumes that nodes are numbered from 0 to N-1 from first stage
(source) to last stage (destination). We also assume that the input graph is multistage.
1486
Chapter 219. Multistage Graph (Shortest Path)
Output:
Source
https://www.geeksforgeeks.org/multistage-graph-shortest-path/
1487
Chapter 220
Creating Nodes
Add one node at a time:
G.add_node(1)
G.add_nodes_from([2,3])
1488
Chapter 220. NetworkX : Python software package for study of complex networks
Creating Edges
Adding one edge at a time:
G.add_edge(1,2)
G.add_edge(3,1)
G.add_edge(2,4)
G.add_edge(4,1)
G.add_edge(9,1)
G.add_edges_from([(1,2),(1,3)])
After adding edges (1,2), (3,1), (2,4), (4,1), (9,1), (1,7), (2,9)
1489
Chapter 220. NetworkX : Python software package for study of complex networks
Graph.remove_node(), Graph.remove_nodes_from(),
Graph.remove_edge() and Graph.remove_edges_from()
1490
Chapter 220. NetworkX : Python software package for study of complex networks
1491
Chapter 220. NetworkX : Python software package for study of complex networks
1492
Chapter 220. NetworkX : Python software package for study of complex networks
G.add_edge(2,4)
G.add_edge(4,1)
G.add_edge(9,1)
G.add_edge(1,7)
G.add_edge(2,9)
# To get all the nodes of a graph
node_list = G.nodes()
print("#1")
print(node_list)
# To get all the edges of a graph
edge_list = G.edges()
print("#2")
print(edge_list)
# To remove a node of a graph
G.remove_node(3)
node_list = G.nodes()
print("#3")
print(node_list)
# To remove an edge of a graph
G.remove_edge(1,2)
edge_list = G.edges()
print("#4")
print(edge_list)
# To find number of nodes
n = G.number_of_nodes()
print("#5")
print(n)
# To find number of edges
m = G.number_of_edges()
print("#6")
print(m)
# To find degree of a node
# d will store degree of node 2
d = G.degree(2)
print("#7")
print(d)
# To find all the neighbor of a node
neighbor_list = G.neighbors(2)
print("#8")
print(neighbor_list)
1493
Chapter 220. NetworkX : Python software package for study of complex networks
#To delete all the nodes and edges
G.clear()
Output :
#1
[1, 2, 3, 4, 7, 9]
#2
[(1, 9), (1, 2), (1, 3), (1, 4), (1, 7), (2, 4), (2, 9)]
#3
[1, 2, 4, 7, 9]
#4
[(1, 9), (1, 4), (1, 7), (2, 4), (2, 9)]
#5
5
#6
5
#7
2
#8
[4, 9]
In the next post, we’ll be discussing how to create weighted graphs, directed graphs, multi
graphs. How to draw graphs. In later posts we’ll see how to use inbuilt functions like
Depth fist search aka dfs, breadth first search aka BFS, dijkstra’s shortest path algorithm.
Source
https://www.geeksforgeeks.org/networkx-python-software-package-study-complex-networks/
1494
Chapter 221
Number of cyclic elements in an array where we can jump according to value - GeeksforGeeks
Given a array arr[] of n integers. For every value arr[i], we can move to arr[i] + 1 clockwise
considering array elements in cycle. We need to count cyclic elements in the array. An
element is cyclic if starting from it and moving to arr[i] + 1 leads to same element.
Examples:
1495
Chapter 221. Number of cyclic elements in an array where we can jump according to value
4 -> 1 -> 1
One simple solution is to check all elements one by one. We follow simple path starting
from every element arr[i], we go to arr[i] + 1. If we come back to a visited element other
than arr[i], we do not count arr[i]. Time complexity of this solution is O(n2 )
An efficient solution is based on below steps.
1) Create a directed graph using array indexes as nodes. We add an edge from i to node
(arr[i] + 1)%n.
2) Once a graph is created we find all strongly connected components using Kosaraju’s
Algorithm
3) We finally return sum of counts of nodes in individual strongly connected component.
1496
Chapter 221. Number of cyclic elements in an array where we can jump according to value
if (!visited[*i])
ans += DFSUtil(*i, visited);
return ans;
}
Graph Graph::getTranspose()
{
Graph g(V);
for (int v = 0; v < V; v++) {
list<int>::iterator i;
for (i = adj[v].begin(); i != adj[v].end(); ++i)
g.adj[*i].push_back(v);
}
return g;
}
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w);
}
void Graph::fillOrder(int v, bool visited[],
stack<int>& Stack)
{
visited[v] = true;
list<int>::iterator i;
for (i = adj[v].begin(); i != adj[v].end(); ++i)
if (!visited[*i])
fillOrder(*i, visited, Stack);
Stack.push(v);
}
// This function mainly returns total count of
// nodes in individual SCCs using Kosaraju's
// algorithm.
int Graph::countSCCNodes()
{
int res = 0;
stack<int> Stack;
bool* visited = new bool[V];
for (int i = 0; i < V; i++)
visited[i] = false;
for (int i = 0; i < V; i++)
if (visited[i] == false)
fillOrder(i, visited, Stack);
Graph gr = getTranspose();
for (int i = 0; i < V; i++)
visited[i] = false;
1497
Chapter 221. Number of cyclic elements in an array where we can jump according to value
1498
Chapter 221. Number of cyclic elements in an array where we can jump according to value
Output:
Source
https://www.geeksforgeeks.org/number-of-cyclic-elements-in-an-array-where-we-can-jump-according-to-value/
1499
Chapter 222
1500
Chapter 222. Number of groups formed in a graph of friends
To count number of groups, we need to simply count connected components in the given
undirected graph. Counting connected components can be easily done using DFS or BFS.
Since this is an undirected graph, the number of times a Depth First Search starts from an
unvisited vertex for every friend is equal to the number of groups formed.
To count number of ways in which we form new groups can be done using simply formula
which is (N1)*(N2)*….(Nn) where Ni is the no of people in i-th group.
1501
Chapter 222. Number of groups formed in a graph of friends
w--;
adj[v].push_back(w);
adj[w].push_back(v);
}
// Returns count of not visited nodes reachable
// from v using DFS.
int Graph::countUtil(int v, bool visited[])
{
int count = 1;
visited[v] = true;
for (auto i=adj[v].begin(); i!=adj[v].end(); ++i)
if (!visited[*i])
count = count + countUtil(*i, visited);
return count;
}
// A DFS based function to Count number of
// existing groups and number of new groups
// that can be formed using a member of
// every group.
void Graph::countGroups()
{
// Mark all the vertices as not visited
bool* visited = new bool[V];
memset(visited, 0, V*sizeof(int));
int existing_groups = 0, new_groups = 1;
for (int i = 0; i < V; i++)
{
// If not in any group.
if (visited[i] == false)
{
existing_groups++;
// Number of new groups that
// can be formed.
new_groups = new_groups *
countUtil(i, visited);
}
}
if (existing_groups == 1)
new_groups = 0;
cout << "No. of existing groups are "
<< existing_groups << endl;
cout << "No. of new groups that can be"
1502
Chapter 222. Number of groups formed in a graph of friends
Output:
Time complexity: O(N + R) where N is the the number of people and R is the number of
relations.
Source
https://www.geeksforgeeks.org/number-groups-formed-graph-friends/
1503
Chapter 223
Input : n = 3, k = 3
Output : 2
Input : n = 4, k = 2
Output : 3
Lets f(n, k) be a function which return number of ways in which one can start from any
node and return to it by visiting K nodes.
If we start and end from one node, then we have K – 1 choices to make for the intermediate
nodes since we have already chosen one node in the beginning. For each intermediate choice,
you have n – 1 options. So, this will yield (n – 1)k – 1 but then we have to remove all the
choices cause smaller loops, so we subtract f(n, k – 1).
So, recurrence relation becomes,
f(n, k) = (n – 1)k – 1 – f(n, k – 1) with base case f(n, 2) = n – 1.
On expanding,
f(n, k) = (n – 1)k – 1 – (n – 1)k – 2 + (n – 1)k – 3 ….. (n – 1) (say eqn 1)
Dividing f(n, k) by (n – 1),
f(n, k)/(n – 1) = (n – 1)k – 2 – (n – 1)k – 3 + (n – 1)k – 4 ….. 1 (say eqn 2)
1504
Chapter 223. Number of loops of size k starting from a specific node
Java
1505
Chapter 223. Number of loops of size k starting from a specific node
// N nodes
static int numOfways(int n, int k)
{
int p = 1;
if (k % 2 != 0)
p = -1;
return (int)(Math.pow(n - 1, k)
+ p * (n - 1)) / n;
}
// Driver code
public static void main(String args[])
{
int n = 4, k = 2;
System.out.println(numOfways(n, k));
}
}
// This code is contributed by Sam007.
Python3
1506
Chapter 223. Number of loops of size k starting from a specific node
C#
PHP
<?php
// PHP Program to find number
// of cycles of length
// k in a graph with n nodes.
// Return the Number of ways from a
// node to make a loop of size K
// in undirected complete connected
// graph of N nodes
1507
Chapter 223. Number of loops of size k starting from a specific node
Output:
Source
https://www.geeksforgeeks.org/number-ways-node-make-loop-size-k-undirected-complete-connected-graph-n-nodes
1508
Chapter 224
Input : N = 2
Allowed path 1: (1, 1) (1, 2)
Allowed path 2: (1, 2) (2, 2)
Output : 6
Cell (2, 1) is not accessible from any cell
and no cell is accessible from it.
(1, 1) - (2, 1)
(1, 2) - (2, 1)
(2, 2) - (2, 1)
(2, 1) - (1, 1)
(2, 1) - (1, 2)
(2, 1) - (2, 2)
Consider each cell as a node, numbered from 1 to N*N. Each cell (x, y) can be map to
number using (x – 1)*N + y. Now, consider each given allowed path as an edge between
nodes. This will form a disjoint set of the connected component. Now, using Depth First
Traversal or Breadth First Traversal, we can easily find the number of nodes or size of a
connected component, say x. Now, count of non-accessible paths are x*(N*N – x). This
way we can find non-accessible paths for each connected path.
1509
Chapter 224. Number of pair of positions in matrix which are not accessible
1510
Chapter 224. Number of pair of positions in matrix which are not accessible
}
return ans;
}
// Inserting the edge between edge.
void insertpath(vector<int> graph[], int N, int x1,
int y1, int x2, int y2)
{
// Mapping the cell coordinate into node number.
int a = (x1 - 1) * N + y1;
int b = (x2 - 1) * N + y2;
// Inserting the edge.
graph[a].push_back(b);
graph[b].push_back(a);
}
// Driven Program
int main()
{
int N = 2;
vector<int> graph[N*N + 1];
insertpath(graph, N, 1, 1, 1, 2);
insertpath(graph, N, 1, 2, 2, 2);
cout << countNonAccessible(graph, N) << endl;
return 0;
}
Output:
Source
https://www.geeksforgeeks.org/number-pair-positions-matrix-not-accessible/
1511
Chapter 225
1512
Chapter 225. Number of shortest paths in an unweighted and directed graph
The idea is to use BFS. We use two arrays called dist[] and paths[], dist[] represents the
shorest distances from source vertex, and paths[] represents the number of different shortest
paths from the source vertex to each of the vertices. Initially all the elements in dist[] are
infinity except source vertex which is equal to 0, since the distance to source vertex from
itself is 0, and all the elements in paths[] are 0 except source vertex which is equal to 1, since
each vertex has a single shortest path to itself. after that, we start traversing the graph
using BFS manner.
Then, for every neighbor Y of each vertex X do:
1) if dist[Y] > dist[X]+1 decrease the dist[Y] to dist[X] +1 and assign the number of paths
of vertex X to number of paths of vertex Y.
2) else if dist[Y] = dist[X] + 1, then add the number of paths of vertex X to the number of
paths of vertex Y.
For example:
Let’s take a look at the below graph. The source vertex is 0. Suppose we traverse on vertex
2, we check all its neighbors, which is only 3.since vertex 3 was already visited when we were
traversed vertex 1, dist[3] = 2 and paths[3] = 1. The second condition is true, so it means
that addtional shortest paths have been found, so we add to the number of paths of vertex
3, the number of paths of vertex 2.
The equal condition happens when we traverse on vertex 5:
1513
Chapter 225. Number of shortest paths in an unweighted and directed graph
1514
Chapter 225. Number of shortest paths in an unweighted and directed graph
// For all neighbors of current vertex do:
for (auto x : adj[curr])
{
// if the current vertex is not yet
// visited, then push it to the queue.
if (visited[x] == false)
{
q.push(x);
visited[x] = true;
}
// check if there is a better path.
if (dist[x] > dist[curr] + 1)
{
dist[x] = dist[curr] + 1;
paths[x] = paths[curr];
}
// additional shortest paths found
else if (dist[x] == dist[curr] + 1)
paths[x] += paths[curr];
}
}
}
// function to find number of different
// shortest paths form given vertex s.
// n is number of vertices.
void findShortestPaths(vector<int> adj[],
int s, int n)
{
int dist[n], paths[n];
for (int i = 0; i < n; i++)
dist[i] = INT_MAX;
for (int i = 0; i < n; i++)
paths[i] = 0;
BFS(adj, s, dist, paths, n);
cout << "Numbers of shortest Paths are: ";
for (int i = 0; i < n; i++)
cout << paths[i] << " ";
}
// A utility function to add an edge in a
// directed graph.
void addEdge(vector<int> adj[], int u, int v)
{
adj[u].push_back(v);
1515
Chapter 225. Number of shortest paths in an unweighted and directed graph
}
// Driver code
int main()
{
int n = 7; // Number of vertices
vector <int> adj[n];
addEdge(adj, 0, 1);
addEdge(adj, 0, 2);
addEdge(adj, 1, 2);
addEdge(adj, 1, 3);
addEdge(adj, 2, 3);
addEdge(adj, 3, 4);
addEdge(adj, 3, 5);
addEdge(adj, 4, 6);
addEdge(adj, 5, 6);
findShortestPaths(adj, 0, 7);
return 0;
}
Output:
Source
https://www.geeksforgeeks.org/number-shortest-paths-unweighted-directed-graph/
1516
Chapter 226
Input: V = 15, E = 14
1 10 // edge 1
1 5 // edge 2
5 10 // edge 3
2 9 // ..
9 15 // ..
2 15 // ..
2 12 // ..
12 15 // ..
13 8 // ..
6 14 // ..
14 3 // ..
3 7 // ..
7 11 // edge 13
11 6 // edge 14
1517
Chapter 226. Number of single cycle components in an undirected graph
Output :2
In the above-mentioned example, the two
single-cyclic-components are composed of
vertices (1, 10, 5) and (6, 11, 7, 3, 14)
respectively.
Now we can easily see that a single-cycle-component is a connected component where every
vertex has the degree as two.
Therefore, in order to solve this problem we first identify all the connected components
of the disconnected graph. For this, we use depth-first search algorithm. For the DFS
algorithm to work, it is required to maintain an array ‘found’ to keep an account of all the
vertices that have been discovered by the recursive function DFS. Once all the elements of a
particular connected component are discovered (like vertices(9, 2, 15, 12) form a connected
graph component ), we check if all the vertices in the component are having the degree
equal to two. If yes, we increase the counter variable ‘count’ which denotes the number of
single-cycle-components found in the given graph. To keep an account of the component we
are presently dealing with, we may use a vector array ‘curr_graph’ as well.
1518
Chapter 226. Number of single cycle components in an undirected graph
DFS(it);
}
// function to add an edge in the graph
void addEdge(vector<int> adj_list[N], int src,
int dest)
{
// for index decrement both src and dest.
src--, dest--;
adj_list[src].push_back(dest);
adj_list[dest].push_back(src);
degree[src]++;
degree[dest]++;
}
int countSingleCycles(int n, int m)
{
// count of cycle graph components
int count = 0;
for (int i = 0; i < n; ++i) {
if (!found[i]) {
curr_graph.clear();
DFS(i);
// traversing the nodes of the
// current graph component
int flag = 1;
for (int v : curr_graph) {
if (degree[v] == 2)
continue;
else {
flag = 0;
break;
}
}
if (flag == 1) {
count++;
}
}
}
return(count);
}
int main()
{
// n->number of vertices
// m->number of edges
int n = 15, m = 14;
1519
Chapter 226. Number of single cycle components in an undirected graph
addEdge(adj_list, 1, 10);
addEdge(adj_list, 1, 5);
addEdge(adj_list, 5, 10);
addEdge(adj_list, 2, 9);
addEdge(adj_list, 9, 15);
addEdge(adj_list, 2, 15);
addEdge(adj_list, 2, 12);
addEdge(adj_list, 12, 15);
addEdge(adj_list, 13, 8);
addEdge(adj_list, 6, 14);
addEdge(adj_list, 14, 3);
addEdge(adj_list, 3, 7);
addEdge(adj_list, 7, 11);
addEdge(adj_list, 11, 6);
cout << countSingleCycles(n, m);
return 0;
}
Output:
Source
https://www.geeksforgeeks.org/number-of-simple-cyclic-components-in-an-undirected-graph/
1520
Chapter 227
Input : n = 4, m = 2
Edges[] = {{2, 3}, {4, 3}}
Output : 2
Input : n = 4, m = 2
Edges[] = {{3, 2}, {3, 4}}
Output : 3
The idea is to iterate through all the edges. And for each edge, mark the source node from
which the edge emerged out. Now, for each node check if it is marked or not. And count
the unmarked nodes.
Algorithm:
1521
Chapter 227. Number of sink nodes in a graph
Output:
1522
Chapter 227. Number of sink nodes in a graph
Source
https://www.geeksforgeeks.org/number-sink-nodes-graph/
1523
Chapter 228
Number of Transpositions in a
Permutation
P = { 5, 1, 4, 2, 3 }:
Here, 5 goes to 1, 1 goes to 2 and so on (according to their indices position):
5 -> 1
1 -> 2
2 -> 4
4 -> 3
3 -> 5
Thus it can be represented as a single cycle: (5, 1, 2, 4, 3).
Now consider the permutation: { 5, 1, 4, 3, 2 }. Here
5 -> 1
1 -> 2
2 -> 5 this closes 1 cycle.
The other cycle is
4 -> 3
3 -> 4
In cycle notation it will be represented as (5, 1, 2) (4, 3).
Transpositions
Now all cycles can be decomposed into a composition of 2 cycles (transpositions). The
1524
Chapter 228. Number of Transpositions in a Permutation
The cycle (5, 1, 2, 4, 3) can be written as (5, 3)(5, 4)(5, 2)(5, 1). 4 transpositions
(even).
Similarly,
(5, 1, 2) -> (5, 2)(5, 1)
(5, 1, 2)(4, 3) -> (5, 2)(5, 1)(4, 3). 3 transpositions (odd).
It is clear from the examples that the number of transpositions from a cycle
= length of the cycle – 1.
Problem
Given a permutation of n numbers P1 , P2 , P3 , … Pn . Calculate the number of transpositions
in it.
Example:
Input: 5 1 4 3 2
Output: 3
Approach: The permutation can be easily represented as a directed graph where the num-
ber of connected components gives the number of cycles. And (the size of each component
– 1) gives the number of transpositions from that cycle.
Example Permutation : { 5, 1, 4, 3, 2 } -> (5, 1, 2)(4, 3)
1525
Chapter 228. Number of Transpositions in a Permutation
1526
Chapter 228. Number of Transpositions in a Permutation
transpositions += ans - 1;
}
}
return transpositions;
}
// Driver Code
int main()
{
int permutation[] = { 5, 1, 4, 3, 2 };
int n = sizeof(permutation) / sizeof(permutation[0]);
cout << noOfTranspositions(permutation, n);
return 0;
}
Java
1527
Chapter 228. Number of Transpositions in a Permutation
visited[i] = 1;
int x = dfs(goesTo[i]);
return (x + 1);
}
// This functio returns the number
// of transpositions in the
// permutation
static int noOfTranspositions(int P[],
int n)
{
// Initializing visited[] array
for (int i = 1; i <= n; i++)
visited[i] = 0;
// building the goesTo[] array
for (int i = 0; i < n; i++)
goesTo[P[i]] = i + 1;
int transpositions = 0;
for (int i = 1; i <= n; i++) {
if (visited[i] == 0) {
int ans = dfs(i);
transpositions += ans - 1;
}
}
return transpositions;
}
// Driver Code
public static void main (String[] args)
{
int permutation[] = { 5, 1, 4, 3, 2 };
int n = permutation.length ;
System.out.println(
noOfTranspositions(permutation, n));
}
}
// This code is contributed by anuj_67.
C#
1528
Chapter 228. Number of Transpositions in a Permutation
class GFG {
static int N = 1000001;
static int []visited = new int[N];
// This array stores which element
// goes to which position
static int []goesTo= new int[N];
// For eg. in { 5, 1, 4, 3, 2 }
// goesTo[1] = 2
// goesTo[2] = 5
// goesTo[3] = 4
// goesTo[4] = 3
// goesTo[5] = 1
// This function returns the size
// of a component cycle
static int dfs(int i)
{
// If it is already visited
if (visited[i] == 1)
return 0;
visited[i] = 1;
int x = dfs(goesTo[i]);
return (x + 1);
}
// This functio returns the number
// of transpositions in the
// permutation
static int noOfTranspositions(int []P,
int n)
{
// Initializing visited[] array
for (int i = 1; i <= n; i++)
visited[i] = 0;
// building the goesTo[] array
for (int i = 0; i < n; i++)
goesTo[P[i]] = i + 1;
int transpositions = 0;
1529
Chapter 228. Number of Transpositions in a Permutation
Output:
Source
https://www.geeksforgeeks.org/number-of-transpositions-in-a-permutation/
1530
Chapter 229
Number of Triangles in an
Undirected Graph
Let A[][] be adjacency matrix representation of graph. If we calculate A3 , then the number
of triangle in Undirected Graph is equal to trace(A3 ) / 6. Where trace(A) is the sum of the
elements on the main diagonal of matrix A.
1531
Chapter 229. Number of Triangles in an Undirected Graph
1532
Chapter 229. Number of Triangles in an Undirected Graph
int aux3[V][V];
// Initialising aux
// matrices with 0
for (int i = 0; i < V; ++i)
for (int j = 0; j < V; ++j)
aux2[i][j] = aux3[i][j] = 0;
// aux2 is graph^2 now printMatrix(aux2);
multiply(graph, graph, aux2);
// after this multiplication aux3 is
// graph^3 printMatrix(aux3);
multiply(graph, aux2, aux3);
int trace = getTrace(aux3);
return trace / 6;
}
// driver code
int main()
{
int graph[V][V] = {{0, 1, 1, 0},
{1, 0, 1, 1},
{1, 1, 0, 1},
{0, 1, 1, 0}
};
printf("Total number of Triangle in Graph : %d\n",
triangleInGraph(graph));
return 0;
}
Java
1533
Chapter 229. Number of Triangles in an Undirected Graph
// Utility function for
// matrix multiplication
void multiply(int A[][], int B[][],
int C[][])
{
for (int i = 0; i < V; i++)
{
for (int j = 0; j < V; j++)
{
C[i][j] = 0;
for (int k = 0; k < V;
k++)
{
C[i][j] += A[i][k]*
B[k][j];
}
}
}
}
// Utility function to calculate
// trace of a matrix (sum of
// diagnonal elements)
int getTrace(int graph[][])
{
int trace = 0;
for (int i = 0; i < V; i++)
{
trace += graph[i][i];
}
return trace;
}
// Utility function for
// calculating number of
// triangles in graph
int triangleInGraph(int graph[][])
{
// To Store graph^2
int[][] aux2 = new int[V][V];
// To Store graph^3
int[][] aux3 = new int[V][V];
// Initialising aux matrices
// with 0
1534
Chapter 229. Number of Triangles in an Undirected Graph
C#
1535
Chapter 229. Number of Triangles in an Undirected Graph
class GFG
{
// Number of vertices
// in the graph
int V = 4;
// Utility function for
// matrix multiplication
void multiply(int [,]A, int [,]B,
int [,]C)
{
for (int i = 0; i < V; i++)
{
for (int j = 0; j < V; j++)
{
C[i, j] = 0;
for (int k = 0; k < V;
k++)
{
C[i, j] += A[i, k]*
B[k, j];
}
}
}
}
// Utility function to
// calculate trace of
// a matrix (sum of
// diagnonal elements)
int getTrace(int [,]graph)
{
int trace = 0;
for (int i = 0; i < V; i++)
{
trace += graph[i, i];
}
return trace;
}
// Utility function for
// calculating number of
// triangles in graph
int triangleInGraph(int [,]graph)
{
// To Store graph^2
int[,] aux2 = new int[V, V];
1536
Chapter 229. Number of Triangles in an Undirected Graph
// To Store graph^3
int[,] aux3 = new int[V, V];
// Initialising aux matrices
// with 0
for (int i = 0; i < V; ++i)
{
for (int j = 0; j < V; ++j)
{
aux2[i, j] = aux3[i, j] = 0;
}
}
// aux2 is graph^2 now
// printMatrix(aux2)
multiply(graph, graph, aux2);
// after this multiplication aux3
// is graph^3 printMatrix(aux3)
multiply(graph, aux2, aux3);
int trace = getTrace(aux3);
return trace / 6;
}
// Driver code
public static void Main()
{
GFG obj = new GFG();
int [,]graph = {{0, 1, 1, 0},
{1, 0, 1, 1},
{1, 1, 0, 1},
{0, 1, 1, 0}};
Console.WriteLine("Total number of " +
"Triangle in Graph : "+
obj.triangleInGraph(graph));
}
}
// This code is contributed by anuj_67.
Output:
1537
Chapter 229. Number of Triangles in an Undirected Graph
Source
https://www.geeksforgeeks.org/number-of-triangles-in-a-undirected-graph/
1538
Chapter 230
We have discussed a method based on graph trace that works for undirected graphs. In
this post a new method is discussed with that is simpler and works for both directed and
undirected graphs.
The idea is to use three nested loops to consider every triplet (i, j, k) and check for the
above condition (there is an edge from i to j, j to k and k to i)
However in an undirected graph, the triplet (i, j, k) can be permuted to give six combina-
tion (See previous post for details). Hence we divide the total count by 6 to get the actual
number of triangles.
In case of directed graph, the number of permutation would be 3 (as order of nodes
becomes relevant). Hence in this case the total number of triangles will be obtained by
dividing total count by 3. For example consider the directed graph given below
Following is the implementation.
C/C++
1539
Chapter 230. Number of Triangles in Directed and Undirected Graphs
1540
Chapter 230. Number of Triangles in Directed and Undirected Graphs
//driver function to check the program
int main()
{
// Create adjacency matrix
// of an undirected graph
int graph[][V] = { {0, 1, 1, 0},
{1, 0, 1, 1},
{1, 1, 0, 1},
{0, 1, 1, 0}
};
// Create adjacency matrix
// of a directed graph
int digraph[][V] = { {0, 0, 1, 0},
{1, 0, 0, 1},
{0, 1, 0, 0},
{0, 0, 1, 0}
};
cout << "The Number of triangles in undirected graph : "
<< countTriangle(graph, false);
cout << "\n\nThe Number of triangles in directed graph : "
<< countTriangle(digraph, true);
return 0;
}
Java
1541
Chapter 230. Number of Triangles in Directed and Undirected Graphs
{
// Initialize result
int count_Triangle = 0;
// Consider every possible
// triplet of edges in graph
for (int i = 0; i < V; i++)
{
for (int j = 0; j < V; j++)
{
for (int k=0; k<V; k++)
{
// check the triplet if it
// satisfies the condition
if (graph[i][j] == 1 &&
graph[j][k] == 1 &&
graph[k][i] == 1)
count_Triangle++;
}
}
}
// if graph is directed , division
// is done by 3 else division
// by 6 is done
if(isDirected == true)
{
count_Triangle /= 3;
}
else
{
count_Triangle /= 6;
}
return count_Triangle;
}
// driver code
public static void main(String args[])
{
// Create adjacency matrix
// of an undirected graph
int graph[][] = {{0, 1, 1, 0},
{1, 0, 1, 1},
{1, 1, 0, 1},
{0, 1, 1, 0}
};
1542
Chapter 230. Number of Triangles in Directed and Undirected Graphs
Python
1543
Chapter 230. Number of Triangles in Directed and Undirected Graphs
[1, 1, 0, 1],
[0, 1, 1, 0 ]]
# Create adjacency matrix of a directed graph
digraph = [[0, 0, 1, 0],
[1, 0, 0, 1],
[0, 1, 0, 0],
[0, 0, 1, 0 ]]
print ("The Number of triangles in undirected graph : %d" %countTriangle(graph, False))
print ("The Number of triangles in directed graph : %d" %countTriangle(digraph, True))
# This code is contributed by Neelam Yadav
C#
1544
Chapter 230. Number of Triangles in Directed and Undirected Graphs
1545
Chapter 230. Number of Triangles in Directed and Undirected Graphs
Console.Write("\n\nThe Number of "
+ "triangles in directed graph : "
+ countTriangle(digraph, true));
}
}
// This code is contributed by anuj_67
PHP
<?php
// PHP program to count triangles
// in a graph. The program is for
// adjacency matrix representation
// of the graph.
// Number of vertices in the graph
$V = 4;
// function to calculate the
// number of triangles in a
// simple directed/undirected
// graph. isDirected is true if
// the graph is directed, its
// false otherwise
function countTriangle($graph,
$isDirected)
{
global $V;
// Initialize result
$count_Triangle = 0;
// Consider every possible
// triplet of edges in graph
for($i = 0; $i < $V; $i++)
{
for($j = 0; $j < $V; $j++)
{
for($k = 0; $k < $V; $k++)
{
// check the triplet if
// it satisfies the condition
if ($graph[$i][$j] and $graph[$j][$k]
and $graph[$k][$i])
$count_Triangle++;
1546
Chapter 230. Number of Triangles in Directed and Undirected Graphs
}
}
}
// if graph is directed ,
// division is done by 3,
// else division by 6 is done
$isDirected? $count_Triangle /= 3 :
$count_Triangle /= 6;
return $count_Triangle;
}
// Driver Code
// Create adjacency matrix
// of an undirected graph
$graph = array(array(0, 1, 1, 0),
array(1, 0, 1, 1),
array(1, 1, 0, 1),
array(0, 1, 1, 0));
// Create adjacency matrix
// of a directed graph
$digraph = array(array(0, 0, 1, 0),
array(1, 0, 0, 1),
array(0, 1, 0, 0),
array(0, 0, 1, 0));
echo "The Number of triangles in undirected graph : "
, countTriangle($graph, false);
echo "\nThe Number of triangles in directed graph : "
, countTriangle($digraph, true);
// This code is contributed by anuj_67
?>
Output:
1547
Chapter 230. Number of Triangles in Directed and Undirected Graphs
Disadvantages:
Improved By : vt_m
Source
https://www.geeksforgeeks.org/number-of-triangles-in-directed-and-undirected-graphs/
1548
Chapter 231
1549
Chapter 231. Number of Unicolored Paths between two nodes
Input : Graph
u, v, color
1, 2, 1
1, 3, 2
2, 3, 3
2, 4, 2
2, 5, 4
3, 5, 3
4, 5, 2
source = 2 destination = 5
Output : 3
Explanation : There are three paths from 2 to 5
2 -> 5 with color red
2 -> 3 - > 5 with color sky blue
2 -> 4 - > 5 with color green
Algorithm :
1. Do dfs traversal on the neighbour nodes of source node.
2. The color between source node and neighbour nodes is known, if the DFS traversal also
have same color, proceed, else stop going on that path.
3. After reaching destination node, increment count by 1.
NOTE : Number of Colors will always be less than number of edges.
1550
Chapter 231. Number of Unicolored Paths between two nodes
// Constructor
public:
Graph(int V, int E);
// function to add an edge to graph
void addEdge(int v, int w, int z);
// finds paths between a and b having
// same color edges
int UniColorPaths(int a, int b);
};
Graph::Graph(int V, int E)
{
this -> V = V;
this -> E = E;
}
void Graph::addEdge(int a, int b, int c)
{
adj[a].push_back({b, c}); // Add b to a’s list.
adj[b].push_back({a, c}); // Add c to b’s list.
}
void Graph::dfs(int x, int y, int col)
{
if (vis[x])
return;
vis[x] = 1;
// mark this as a possible color to reach s to d
if (x == y)
{
color[col] = 1;
return;
}
// if the next edge is also of same color
for (int i = 0; i < int(adj[x].size()); i++)
if (adj[x][i].second == col)
dfs(adj[x][i].first, y, col);
}
// function that finds paths between a and b
// such that all edges are same colored
// It uses recursive dfs()
int Graph::UniColorPaths(int a, int b)
{
1551
Chapter 231. Number of Unicolored Paths between two nodes
// dfs on nodes directly connected to source
for (int i = 0; i < int(adj[a].size()); i++)
{
dfs(a, b, adj[a][i].second);
// to visit again visited nodes
memset(vis, 0, sizeof(vis));
}
int cur = 0;
for (int i = 0; i <= E; i++)
cur += color[i];
return (cur);
}
// driver code
int main()
{
// Create a graph given in the above diagram
Graph g(5, 7);
g.addEdge(1, 2, 1);
g.addEdge(1, 3, 2);
g.addEdge(2, 3, 3);
g.addEdge(2, 4, 2);
g.addEdge(2, 5, 4);
g.addEdge(3, 5, 3);
g.addEdge(4, 5, 2);
int s = 2; // source
int d = 5; // destination
cout << "Number of unicolored paths : ";
cout << g.UniColorPaths(s, d) << endl;
return 0;
}
Output:
Source
https://www.geeksforgeeks.org/number-unicolored-paths-two-nodes/
1552
Chapter 232
Input1 : m = 5, n = 5, k = 2, r = 1,
X = {1, 3}, Y = {3, 3}
Output1 : Possible
Input2 : m = 5, n = 5, k = 2, r = 1,
X = {1, 1}, Y = {2, 3}.
Output2 : Not Possible
Approach : Check if the centre of a cell (i, j) of the rectangle comes within any of the
circles then do not traverse through that cell and mark that as ‘blocked’. Mark rest of the
cells initially as ‘unvisited’. Then use BFS to find out shortest path of each cell from starting
position. If the end cell is visited then we will return “Possible” otherwise “Not Possible”.
Algorithm :
1553
Chapter 232. Path in a Rectangle with Circles
3. Now, apply BFS from the starting cell and if a cell can be reached then change the
value of that cell to 1.
4. If the value of the ending cell is 1, then return ‘Possible’, otherwise return ‘Not Possi-
ble’.
C++
1554
Chapter 232. Path in a Rectangle with Circles
1555
Chapter 232. Path in a Rectangle with Circles
qu.push_back(v);
}
// check right cell
if ((eley > n - 1) &&
(rect[elex][eley + 1] == 0))
{
rect[elex][eley + 1] = 1;
vector<int> v = {elex, eley + 1};
qu.push_back(v);
}
// check bottom-left cell
if ((elex < m - 1) && (eley > 0) &&
(rect[elex + 1][eley - 1] == 0))
{
rect[elex + 1][eley - 1] = 1;
vector<int> v = {elex + 1, eley - 1};
qu.push_back(v);
}
// check bottom cell
if ((elex < m - 1) &&
(rect[elex + 1][eley] == 0))
{
rect[elex + 1][eley] = 1;
vector<int> v = {elex + 1, eley};
qu.push_back(v);
}
// check bottom-right cell
if ((elex < m - 1) && (eley < n - 1) &&
(rect[elex + 1][eley + 1] == 0))
{
rect[elex + 1][eley + 1] = 1;
vector<int> v = {elex + 1, eley + 1};
qu.push_back(v);
}
}
// Now if the end cell (i.e. bottom right cell)
// is 1(reachable) then we will send true.
return (rect[m - 1][n - 1] == 1);
}
// Driver Program
int main() {
1556
Chapter 232. Path in a Rectangle with Circles
Output:
Possible
Not Possible
Time Complexity : It takes O(m*n*k) time to compute whether a cell is within or not
in any circle. And it takes O(V+E) time in BFS. Here, number of edges in m*n grid is
m*(n-1)+n*(m-1) and vertices m*n. So it takes O(m*n) time in DFS. Hence, the time
complexity is O(m*n*k). The complexity can be improved if we iterate through each circles
and mark -1 the cells which are coming within it.
Source
https://www.geeksforgeeks.org/path-rectangle-containing-circles/
1557
Chapter 233
Paths to travel each nodes using each edge (Seven Bridges of Königsberg) - GeeksforGeeks
There are n nodes and m bridges in between these nodes. Print the possible path through
each node using each edges (if possible), traveling through each edges only once.
Examples :
1558
Chapter 233. Paths to travel each nodes using each edge (Seven Bridges of Königsberg)
[0, 1, 0, 1, 0],
[0, 1, 1, 0, 0],
[1, 0, 0, 0, 0]]
It is one of the famous problems in Graph Theory and known as problem of “Seven Bridges
of Königsberg”. This problem was solved by famous mathematician Leonhard Euler in 1735.
This problem is also considered as the beginning of Graph Theory.
The problem back then was that: There was 7 bridges connecting 4 lands around the city
of Königsberg in Prussia. Was there any way to start from any of the land and go trough
each of the bridges once and only once? Please see these wikipedia images for more clarity.
Euler first introduced graph theory to solve this problem. He considered each of the lands
as a node of a graph and each bridge in between as an edge in between. Now he calculated
if there is any Eulerian Path in that graph. If there is an Eulerian path then there is a
solution otherwise not.
Problem here, is a generalized version of the problem in 1735.
Below is the implementation :
1559
Chapter 233. Paths to travel each nodes using each edge (Seven Bridges of Königsberg)
{
this->V = V;
adj = new list<int>[V];
}
~Graph()
{
delete [] adj;
}
// functions to add and remove edge
void addEdge(int u, int v)
{
adj[u].push_back(v);
adj[v].push_back(u);
}
void rmvEdge(int u, int v);
// Methods to print Eulerian tour
void printEulerTour();
void printEulerUtil(int s);
// This function returns count of vertices
// reachable from v. It does DFS
int DFSCount(int v, bool visited[]);
// Utility function to check if edge u-v
// is a valid next edge in Eulerian trail or circuit
bool isValidNextEdge(int u, int v);
};
/* The main function that print Eulerian Trail.
It first finds an odd degree vertex (if there is any)
and then calls printEulerUtil() to print the path */
void Graph::printEulerTour()
{
// Find a vertex with odd degree
int u = 0;
for (int i = 0; i < V; i++)
if (adj[i].size() & 1)
{
u = i;
break;
}
// Print tour starting from oddv
printEulerUtil(u);
1560
Chapter 233. Paths to travel each nodes using each edge (Seven Bridges of Königsberg)
1561
Chapter 233. Paths to travel each nodes using each edge (Seven Bridges of Königsberg)
bool visited[V];
memset(visited, false, V);
int count1 = DFSCount(u, visited);
// 2.b) Remove edge (u, v) and after removing
// the edge, count vertices reachable from u
rmvEdge(u, v);
memset(visited, false, V);
int count2 = DFSCount(u, visited);
// 2.c) Add the edge back to the graph
addEdge(u, v);
// 2.d) If count1 is greater, then edge (u, v)
// is a bridge
return (count1 > count2)? false: true;
}
// This function removes edge u-v from graph.
// It removes the edge by replacing adjcent
// vertex value with -1.
void Graph::rmvEdge(int u, int v)
{
// Find v in adjacency list of u and replace
// it with -1
list<int>::iterator iv = find(adj[u].begin(),
adj[u].end(), v);
*iv = -1;
// Find u in adjacency list of v and replace
// it with -1
list<int>::iterator iu = find(adj[v].begin(),
adj[v].end(), u);
*iu = -1;
}
// A DFS based function to count reachable
// vertices from v
int Graph::DFSCount(int v, bool visited[])
{
// Mark the current node as visited
visited[v] = true;
int count = 1;
// Recur for all vertices adjacent to this vertex
list<int>::iterator i;
for (i = adj[v].begin(); i != adj[v].end(); ++i)
1562
Chapter 233. Paths to travel each nodes using each edge (Seven Bridges of Königsberg)
Output:
Source
https://www.geeksforgeeks.org/paths-travel-nodes-using-edgeseven-bridges-konigsberg/
1563
Chapter 234
Permutation of numbers such that sum of two consecutive numbers is a perfect square -
GeeksforGeeks
Prerequisite: Hamiltonian Cycle
Given an integer n(>=2), find a permutation of numbers from 1 to n such that the sum of
two consecutive numbers of that permutation is a perfect square. If that kind of permutation
is not possible to print “No Solution”.
Examples:
Input : 17
Output : [16, 9, 7, 2, 14, 11, 5, 4, 12, 13, 3, 6, 10, 15, 1, 8, 17]
Explanation : 16+9 = 25 = 5*5, 9+7 = 16 = 4*4, 7+2 = 9 = 3*3 and so on.
Input: 20
Output: No Solution
Input : 25
Output : [2, 23, 13, 12, 24, 25, 11, 14, 22, 3, 1, 8,
17, 19, 6, 10, 15, 21, 4, 5, 20, 16, 9, 7, 18]
Method:
We can represent a graph, where numbers from 1 to n are the nodes of the graph and there
is an edge between ith and jth node if (i+j) is a perfect square. Then we can search if there
is any Hamiltonian Path in the graph. If there is at least one path then we print a path
otherwise we print “No Solution”.
1564
Chapter 234. Permutation of numbers such that sum of two consecutive numbers is a
perfect square
Approach:
Python3
1565
Chapter 234. Permutation of numbers such that sum of two consecutive numbers is a
perfect square
# false.
for i in range(pos):
if (path[i] == v):
return False
# If none of the previous cases satisfies
# then we can add v to the path in the
# position pos. Hence return true.
return True
# Function to form a path based on the graph.
def formpath(graph, path, pos):
# If all the elements are included in the
# path i.e. length of the path is n then
# return true i.e. path formed.
n = len(graph) - 1
if (pos == n + 1):
return True
# This loop checks for each element if it
# can be fitted as the next element of the
# path and recursively finds the next
# element of the path.
for v in range(1, n + 1):
if issafe(v, graph, path, pos):
path[pos] = v
# Recurs for next element of the path.
if (formpath(graph, path, pos + 1) == True):
return True
# If adding v does not give a solution
# then remove it from path
path[pos] = -1
# if any vertex cannot be added with the
# formed path then return false and
# backtracks.
return False
# Function to find out sum-square series.
def hampath(n):
# base case: if n = 1 there is no solution
if n == 1:
1566
Chapter 234. Permutation of numbers such that sum of two consecutive numbers is a
perfect square
Output:
1567
Chapter 234. Permutation of numbers such that sum of two consecutive numbers is a
perfect square
Discussion:
This backtracking algorithm takes exponential time to find Hamiltonian Path. Hence the
time complexity of this algorithm is exponential.
In the last part of the hampath(n) function if we just print the path rather returning it then
it will print all possible Hamiltonian Path i.e. all possible representations.
Actually we will first get a representation like this for n = 15. For n<15 there is no repre-
sentation. For n = 18, 19, 20, 21, 22, 24 there is also no Hamiltonian Path. For rest of the
numbers it works well.
Reference: Numberphile
Source
https://www.geeksforgeeks.org/permutation-numbers-sum-two-consecutive-numbers-perfect-square/
1568
Chapter 235
1569
Chapter 235. Prim’s Algorithm (Simple Implementation for Adjacency Matrix
Representation)
if (u == v)
return false;
if (inMST[u] == false && inMST[v] == false)
return false;
else if (inMST[u] == true && inMST[v] == true)
return false;
return true;
}
void primMST(int cost[][V])
{
vector<bool> inMST(V, false);
// Include first vertex in MST
inMST[0] = true;
// Keep adding edges while number of included
// edges does not become V-1.
int edge_count = 0, mincost = 0;
while (edge_count < V - 1) {
// Find minimum weight valid edge.
int min = INT_MAX, a = -1, b = -1;
for (int i = 0; i < V; i++) {
for (int j = 0; j < V; j++) {
if (cost[i][j] < min) {
if (isValidEdge(i, j, inMST)) {
min = cost[i][j];
a = i;
b = j;
}
}
}
}
if (a != -1 && b != -1) {
printf("Edge %d:(%d, %d) cost: %d \n",
edge_count++, a, b, min);
mincost = mincost + min;
inMST[b] = inMST[a] = true;
}
}
printf("\n Minimum cost= %d \n", mincost);
}
// driver program to test above function
int main()
{
/* Let us create the following graph
1570
Chapter 235. Prim’s Algorithm (Simple Implementation for Adjacency Matrix
Representation)
2 3
(0)--(1)--(2)
| / \ |
6| 8/ \5 |7
| / \ |
(3)-------(4)
9 */
int cost[][V] = {
{ INT_MAX, 2, INT_MAX, 6, INT_MAX },
{ 2, INT_MAX, 3, 8, 5 },
{ INT_MAX, 3, INT_MAX, INT_MAX, 7 },
{ 6, 8, INT_MAX, INT_MAX, 9 },
{ INT_MAX, 5, 7, 9, INT_MAX },
};
// Print the solution
primMST(cost);
return 0;
}
Output:
Minimum cost= 16
Source
https://www.geeksforgeeks.org/prims-algorithm-simple-implementation-for-adjacency-matrix-representation/
1571
Chapter 236
• Prim’s Algorithm for Adjacency Matrix Representation (In C/C++ with time com-
plexity O(v2 )
1572
Chapter 236. Prim’s algorithm using priority_queue in STL
• Prim’s Algorithm for Adjacency List Representation (In C with Time Complexity
O(ELogV))
The second implementation is time complexity wise better, but is really complex as we
have implemented our own priority queue. STL provides priority_queue, but the provided
priority queue doesn’t support decrease key operation. And in Prim’s algorithm, we need a
priority queueand below operations on priority queue :
• ExtractMin : from all those vertices which have not yet been included in MST, we
need to get vertex with minimum key value.
• DecreaseKey : After extracting vertex we need to update keys of its adjacent vertices,
and if new key is smaller, then update that in data structure.
The algorithm discussed here can be modified so that decrease key is never required. The
idea is, not to insert all vertices in priority queue, but only those which are not MST and
have been visited through a vertex that has included in MST. We keep track of vertices
included in MST in a separate boolean array inMST[].
1573
Chapter 236. Prim’s algorithm using priority_queue in STL
1574
Chapter 236. Prim’s algorithm using priority_queue in STL
1575
Chapter 236. Prim’s algorithm using priority_queue in STL
// 'i' is used to get all adjacent vertices of a vertex
list< pair<int, int> >::iterator i;
for (i = adj[u].begin(); i != adj[u].end(); ++i)
{
// Get vertex label and weight of current adjacent
// of u.
int v = (*i).first;
int weight = (*i).second;
// If v is not in MST and weight of (u,v) is smaller
// than current key of v
if (inMST[v] == false && key[v] > weight)
{
// Updating key of v
key[v] = weight;
pq.push(make_pair(key[v], v));
parent[v] = u;
}
}
}
// Print edges of MST using parent array
for (int i = 1; i < V; ++i)
printf("%d - %d\n", parent[i], i);
}
// Driver program to test methods of graph class
int main()
{
// create the graph given in above fugure
int V = 9;
Graph g(V);
// making above shown graph
g.addEdge(0, 1, 4);
g.addEdge(0, 7, 8);
g.addEdge(1, 2, 8);
g.addEdge(1, 7, 11);
g.addEdge(2, 3, 7);
g.addEdge(2, 8, 2);
g.addEdge(2, 5, 4);
g.addEdge(3, 4, 9);
g.addEdge(3, 5, 14);
g.addEdge(4, 5, 10);
g.addEdge(5, 6, 2);
g.addEdge(6, 7, 1);
g.addEdge(6, 8, 6);
1576
Chapter 236. Prim’s algorithm using priority_queue in STL
g.addEdge(7, 8, 7);
g.primMST();
return 0;
}
1577
Chapter 236. Prim’s algorithm using priority_queue in STL
// Insert source itself in priority queue and initialize
// its key as 0.
pq.push(make_pair(0, src));
key[src] = 0;
/* Looping till priority queue becomes empty */
while (!pq.empty())
{
// The first vertex in pair is the minimum key
// vertex, extract it from priority queue.
// vertex label is stored in second of pair (it
// has to be done this way to keep the vertices
// sorted key (key must be first item
// in pair)
int u = pq.top().second;
pq.pop();
inMST[u] = true; // Include vertex in MST
// Traverse all adjacent of u
for (auto x : adj[u])
{
// Get vertex label and weight of current adjacent
// of u.
int v = x.first;
int weight = x.second;
// If v is not in MST and weight of (u,v) is smaller
// than current key of v
if (inMST[v] == false && key[v] > weight)
{
// Updating key of v
key[v] = weight;
pq.push(make_pair(key[v], v));
parent[v] = u;
}
}
}
// Print edges of MST using parent array
for (int i = 1; i < V; ++i)
printf("%d - %d\n", parent[i], i);
}
// Driver program to test methods of graph class
int main()
{
1578
Chapter 236. Prim’s algorithm using priority_queue in STL
int V = 9;
vector<iPair > adj[V];
// making above shown graph
addEdge(adj, 0, 1, 4);
addEdge(adj, 0, 7, 8);
addEdge(adj, 1, 2, 8);
addEdge(adj, 1, 7, 11);
addEdge(adj, 2, 3, 7);
addEdge(adj, 2, 8, 2);
addEdge(adj, 2, 5, 4);
addEdge(adj, 3, 4, 9);
addEdge(adj, 3, 5, 14);
addEdge(adj, 4, 5, 10);
addEdge(adj, 5, 6, 2);
addEdge(adj, 6, 7, 1);
addEdge(adj, 6, 8, 6);
addEdge(adj, 7, 8, 7);
primMST(adj, V);
return 0;
}
Note : Like Dijkstra’s priority_queue implementation, we may have multiple entries for
same vertex as we do not (and we can not) make isMST[v] = true in if condition.
But as explained in Dijkstra’s algorithm, time complexity remains O(E Log V) as there will
be at most O(E) vertices in priority queue and O(Log E) is same as O(Log V).
Unlike Dijkstra’s implementation, a boolean array inMST[] is mandatory here because the
key values of newly inserted items can be less than the key values of extracted items. So we
must not consider extracted items.
This article is contributed by Shubham Agrawal. Please write comments if you find
anything incorrect, or you want to share more information about the topic discussed above
1579
Chapter 236. Prim’s algorithm using priority_queue in STL
Source
https://www.geeksforgeeks.org/prims-algorithm-using-priority_queue-stl/
1580
Chapter 237
1581
Chapter 237. Prim’s Minimum Spanning Tree (MST) Greedy Algo-5
are used only for vertices which are not yet included in MST, the key value for these vertices
indicate the minimum weight edges connecting them to the set of vertices included in MST.
Let us understand with the following example:
The set mstSet is initially empty and keys assigned to vertices are {0, INF, INF, INF, INF,
INF, INF, INF} where INF indicates infinite. Now pick the vertex with minimum key value.
The vertex 0 is picked, include it in mstSet. So mstSet becomes {0}. After including to
mstSet, update key values of adjacent vertices. Adjacent vertices of 0 are 1 and 7. The key
values of 1 and 7 are updated as 4 and 8. Following subgraph shows vertices and their key
values, only the vertices with finite key values are shown. The vertices included in MST are
shown in green color.
Pick the vertex with minimum key value and not already included in MST (not in mstSET).
The vertex 1 is picked and added to mstSet. So mstSet now becomes {0, 1}. Update the
key values of adjacent vertices of 1. The key value of vertex 2 becomes 8.
Pick the vertex with minimum key value and not already included in MST (not in mstSET).
We can either pick vertex 7 or vertex 2, let vertex 7 is picked. So mstSet now becomes {0,
1, 7}. Update the key values of adjacent vertices of 7. The key value of vertex 6 and 8
becomes finite (7 and 1 respectively).
1582
Chapter 237. Prim’s Minimum Spanning Tree (MST) Greedy Algo-5
Pick the vertex with minimum key value and not already included in MST (not in mstSET).
Vertex 6 is picked. So mstSet now becomes {0, 1, 7, 6}. Update the key values of adjacent
vertices of 6. The key value of vertex 5 and 8 are updated.
We repeat the above steps until mstSet includes all vertices of given graph. Finally, we get
the following graph.
1583
Chapter 237. Prim’s Minimum Spanning Tree (MST) Greedy Algo-5
1584
Chapter 237. Prim’s Minimum Spanning Tree (MST) Greedy Algo-5
Java
1585
Chapter 237. Prim’s Minimum Spanning Tree (MST) Greedy Algo-5
1586
Chapter 237. Prim’s Minimum Spanning Tree (MST) Greedy Algo-5
// To represent set of vertices not yet included in MST
Boolean mstSet[] = new Boolean[V];
// Initialize all keys as INFINITE
for (int i = 0; i < V; i++)
{
key[i] = Integer.MAX_VALUE;
mstSet[i] = false;
}
// Always include first 1st vertex in MST.
key[0] = 0; // Make key 0 so that this vertex is
// picked as first vertex
parent[0] = -1; // First node is always root of MST
// The MST will have V vertices
for (int count = 0; count < V-1; count++)
{
// Pick thd minimum key vertex from the set of vertices
// not yet included in MST
int u = minKey(key, mstSet);
// Add the picked vertex to the MST Set
mstSet[u] = true;
// Update key value and parent index of the adjacent
// vertices of the picked vertex. Consider only those
// vertices which are not yet included in MST
for (int v = 0; v < V; v++)
// graph[u][v] is non zero only for adjacent vertices of m
// mstSet[v] is false for vertices not yet included in MST
// Update the key only if graph[u][v] is smaller than key[v]
if (graph[u][v]!=0 && mstSet[v] == false &&
graph[u][v] < key[v])
{
parent[v] = u;
key[v] = graph[u][v];
}
}
// print the constructed MST
printMST(parent, V, graph);
}
public static void main (String[] args)
{
1587
Chapter 237. Prim’s Minimum Spanning Tree (MST) Greedy Algo-5
Python
1588
Chapter 237. Prim’s Minimum Spanning Tree (MST) Greedy Algo-5
for v in range(self.V):
if key[v] < min and mstSet[v] == False:
min = key[v]
min_index = v
return min_index
# Function to construct and print MST for a graph
# represented using adjacency matrix representation
def primMST(self):
#Key values used to pick minimum weight edge in cut
key = [sys.maxint] * self.V
parent = [None] * self.V # Array to store constructed MST
# Make key 0 so that this vertex is picked as first vertex
key[0] = 0
mstSet = [False] * self.V
parent[0] = -1 # First node is always the root of
for cout in range(self.V):
# Pick the minimum distance vertex from
# the set of vertices not yet processed.
# u is always equal to src in first iteration
u = self.minKey(key, mstSet)
# Put the minimum distance vertex in
# the shortest path tree
mstSet[u] = True
# Update dist value of the adjacent vertices
# of the picked vertex only if the current
# distance is greater than new distance and
# the vertex in not in the shotest path tree
for v in range(self.V):
# graph[u][v] is non zero only for adjacent vertices of m
# mstSet[v] is false for vertices not yet included in MST
# Update the key only if graph[u][v] is smaller than key[v]
if self.graph[u][v] > 0 and mstSet[v] == False and key[v] > self.graph[u][v]:
key[v] = self.graph[u][v]
parent[v] = u
self.printMST(parent)
g = Graph(5)
g.graph = [ [0, 2, 0, 6, 0],
1589
Chapter 237. Prim’s Minimum Spanning Tree (MST) Greedy Algo-5
[2, 0, 3, 8, 5],
[0, 3, 0, 0, 7],
[6, 8, 0, 0, 9],
[0, 5, 7, 9, 0]]
g.primMST();
# Contributed by Divyanshu Mehta
C#
1590
Chapter 237. Prim’s Minimum Spanning Tree (MST) Greedy Algo-5
1591
Chapter 237. Prim’s Minimum Spanning Tree (MST) Greedy Algo-5
// Update key value and parent
// index of the adjacent vertices
// of the picked vertex. Consider
// only those vertices which are
// not yet included in MST
for (int v = 0; v < V; v++)
// graph[u][v] is non zero only
// for adjacent vertices of m
// mstSet[v] is false for vertices
// not yet included in MST Update
// the key only if graph[u][v] is
// smaller than key[v]
if (graph[u,v] != 0 && mstSet[v] == false &&
graph[u,v] < key[v])
{
parent[v] = u;
key[v] = graph[u,v];
}
}
// print the constructed MST
printMST(parent, V, graph);
}
// Driver Code
public static void Main ()
{
/* Let us create the following graph
2 3
(0)--(1)--(2)
| / \ |
6| 8/ \5 |7
| / \ |
(3)-------(4)
9 */
int [,]graph = new int[,] {{0, 2, 0, 6, 0},
{2, 0, 3, 8, 5},
{0, 3, 0, 0, 7},
{6, 8, 0, 0, 9},
{0, 5, 7, 9, 0}};
// Print the solution
primMST(graph);
}
1592
Chapter 237. Prim’s Minimum Spanning Tree (MST) Greedy Algo-5
}
// This code is contributed by anuj_67.
Output:
Edge Weight
0 - 1 2
1 - 2 3
0 - 3 6
1 - 4 5
Time Complexity of the above program is O(V^2). If the input graph is represented using
adjacency list, then the time complexity of Prim’s algorithm can be reduced to O(E log V)
with the help of binary heap. Please see Prim’s MST for Adjacency List Representation for
more details.
Improved By : vt_m, AnkurKarmakar
Source
https://www.geeksforgeeks.org/prims-minimum-spanning-tree-mst-greedy-algo-5/
1593
Chapter 238
1594
Chapter 238. Prim’s MST for Adjacency List Representation Greedy Algo-6
Initially, key value of first vertex is 0 and INF (infinite) for all other vertices. So vertex 0
is extracted from Min Heap and key values of vertices adjacent to 0 (1 and 7) are updated.
Min Heap contains all vertices except vertex 0.
The vertices in green color are the vertices included in MST.
Since key value of vertex 1 is minimum among all nodes in Min Heap, it is extracted from
Min Heap and key values of vertices adjacent to 1 are updated (Key is updated if the a
vertex is not in Min Heap and previous key value is greater than the weight of edge from 1
to the adjacent). Min Heap contains all vertices except vertex 0 and 1.
Since key value of vertex 7 is minimum among all nodes in Min Heap, it is extracted from
Min Heap and key values of vertices adjacent to 7 are updated (Key is updated if the a
vertex is not in Min Heap and previous key value is greater than the weight of edge from 7
to the adjacent). Min Heap contains all vertices except vertex 0, 1 and 7.
Since key value of vertex 6 is minimum among all nodes in Min Heap, it is extracted from
Min Heap and key values of vertices adjacent to 6 are updated (Key is updated if the a
1595
Chapter 238. Prim’s MST for Adjacency List Representation Greedy Algo-6
vertex is not in Min Heap and previous key value is greater than the weight of edge from 6
to the adjacent). Min Heap contains all vertices except vertex 0, 1, 7 and 6.
The above steps are repeated for rest of the nodes in Min Heap till Min Heap becomes empty
C++
// C / C++ program for Prim's MST for adjacency list representation of graph
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
// A structure to represent a node in adjacency list
struct AdjListNode {
int dest;
int weight;
struct AdjListNode* next;
};
// A structure to represent an adjacency list
struct AdjList {
struct AdjListNode* head; // pointer to head node of list
};
// A structure to represent a graph. A graph is an array of adjacency lists.
// Size of array will be V (number of vertices in graph)
struct Graph {
int V;
struct AdjList* array;
};
// A utility function to create a new adjacency list node
struct AdjListNode* newAdjListNode(int dest, int weight)
1596
Chapter 238. Prim’s MST for Adjacency List Representation Greedy Algo-6
{
struct AdjListNode* newNode = (struct AdjListNode*)malloc(sizeof(struct AdjListNode));
newNode->dest = dest;
newNode->weight = weight;
newNode->next = NULL;
return newNode;
}
// A utility function that creates a graph of V vertices
struct Graph* createGraph(int V)
{
struct Graph* graph = (struct Graph*)malloc(sizeof(struct Graph));
graph->V = V;
// Create an array of adjacency lists. Size of array will be V
graph->array = (struct AdjList*)malloc(V * sizeof(struct AdjList));
// Initialize each adjacency list as empty by making head as NULL
for (int i = 0; i < V; ++i)
graph->array[i].head = NULL;
return graph;
}
// Adds an edge to an undirected graph
void addEdge(struct Graph* graph, int src, int dest, int weight)
{
// Add an edge from src to dest. A new node is added to the adjacency
// list of src. The node is added at the begining
struct AdjListNode* newNode = newAdjListNode(dest, weight);
newNode->next = graph->array[src].head;
graph->array[src].head = newNode;
// Since graph is undirected, add an edge from dest to src also
newNode = newAdjListNode(src, weight);
newNode->next = graph->array[dest].head;
graph->array[dest].head = newNode;
}
// Structure to represent a min heap node
struct MinHeapNode {
int v;
int key;
};
// Structure to represent a min heap
struct MinHeap {
int size; // Number of heap nodes present currently
1597
Chapter 238. Prim’s MST for Adjacency List Representation Greedy Algo-6
1598
Chapter 238. Prim’s MST for Adjacency List Representation Greedy Algo-6
if (smallest != idx) {
// The nodes to be swapped in min heap
MinHeapNode* smallestNode = minHeap->array[smallest];
MinHeapNode* idxNode = minHeap->array[idx];
// Swap positions
minHeap->pos[smallestNode->v] = idx;
minHeap->pos[idxNode->v] = smallest;
// Swap nodes
swapMinHeapNode(&minHeap->array[smallest], &minHeap->array[idx]);
minHeapify(minHeap, smallest);
}
}
// A utility function to check if the given minHeap is ampty or not
int isEmpty(struct MinHeap* minHeap)
{
return minHeap->size == 0;
}
// Standard function to extract minimum node from heap
struct MinHeapNode* extractMin(struct MinHeap* minHeap)
{
if (isEmpty(minHeap))
return NULL;
// Store the root node
struct MinHeapNode* root = minHeap->array[0];
// Replace root node with last node
struct MinHeapNode* lastNode = minHeap->array[minHeap->size - 1];
minHeap->array[0] = lastNode;
// Update position of last node
minHeap->pos[root->v] = minHeap->size - 1;
minHeap->pos[lastNode->v] = 0;
// Reduce heap size and heapify root
--minHeap->size;
minHeapify(minHeap, 0);
return root;
}
// Function to decreasy key value of a given vertex v. This function
1599
Chapter 238. Prim’s MST for Adjacency List Representation Greedy Algo-6
// uses pos[] of min heap to get the current index of node in min heap
void decreaseKey(struct MinHeap* minHeap, int v, int key)
{
// Get the index of v in heap array
int i = minHeap->pos[v];
// Get the node and update its key value
minHeap->array[i]->key = key;
// Travel up while the complete tree is not hepified.
// This is a O(Logn) loop
while (i && minHeap->array[i]->key < minHeap->array[(i - 1) / 2]->key) {
// Swap this node with its parent
minHeap->pos[minHeap->array[i]->v] = (i - 1) / 2;
minHeap->pos[minHeap->array[(i - 1) / 2]->v] = i;
swapMinHeapNode(&minHeap->array[i], &minHeap->array[(i - 1) / 2]);
// move to parent index
i = (i - 1) / 2;
}
}
// A utility function to check if a given vertex
// 'v' is in min heap or not
bool isInMinHeap(struct MinHeap* minHeap, int v)
{
if (minHeap->pos[v] < minHeap->size)
return true;
return false;
}
// A utility function used to print the constructed MST
void printArr(int arr[], int n)
{
for (int i = 1; i < n; ++i)
printf("%d - %d\n", arr[i], i);
}
// The main function that constructs Minimum Spanning Tree (MST)
// using Prim's algorithm
void PrimMST(struct Graph* graph)
{
int V = graph->V; // Get the number of vertices in graph
int parent[V]; // Array to store constructed MST
int key[V]; // Key values used to pick minimum weight edge in cut
// minHeap represents set E
struct MinHeap* minHeap = createMinHeap(V);
1600
Chapter 238. Prim’s MST for Adjacency List Representation Greedy Algo-6
// Initialize min heap with all vertices. Key value of
// all vertices (except 0th vertex) is initially infinite
for (int v = 1; v < V; ++v) {
parent[v] = -1;
key[v] = INT_MAX;
minHeap->array[v] = newMinHeapNode(v, key[v]);
minHeap->pos[v] = v;
}
// Make key value of 0th vertex as 0 so that it
// is extracted first
key[0] = 0;
minHeap->array[0] = newMinHeapNode(0, key[0]);
minHeap->pos[0] = 0;
// Initially size of min heap is equal to V
minHeap->size = V;
// In the followin loop, min heap contains all nodes
// not yet added to MST.
while (!isEmpty(minHeap)) {
// Extract the vertex with minimum key value
struct MinHeapNode* minHeapNode = extractMin(minHeap);
int u = minHeapNode->v; // Store the extracted vertex number
// Traverse through all adjacent vertices of u (the extracted
// vertex) and update their key values
struct AdjListNode* pCrawl = graph->array[u].head;
while (pCrawl != NULL) {
int v = pCrawl->dest;
// If v is not yet included in MST and weight of u-v is
// less than key value of v, then update key value and
// parent of v
if (isInMinHeap(minHeap, v) && pCrawl->weight < key[v]) {
key[v] = pCrawl->weight;
parent[v] = u;
decreaseKey(minHeap, v, key[v]);
}
pCrawl = pCrawl->next;
}
}
// print edges of MST
printArr(parent, V);
}
1601
Chapter 238. Prim’s MST for Adjacency List Representation Greedy Algo-6
Java
1602
Chapter 238. Prim’s MST for Adjacency List Representation Greedy Algo-6
}
}
static class Graph {
// Number of vertices in the graph
int V;
// List of adjacent nodes of a given vertex
LinkedList<node1>[] adj;
// Constructor
Graph(int e)
{
V = e;
adj = new LinkedList[V];
for (int o = 0; o < V; o++)
adj[o] = new LinkedList<>();
}
}
// class to represent a node in PriorityQueue
// Stores a vertex and its corresponding
// key value
class node {
int vertex;
int key;
}
// Comparator class created for PriorityQueue
// returns 1 if node0.key > node1.key
// returns 0 if node0.key < node1.key and
// returns -1 otherwise
class comparator implements Comparator<node> {
@Override
public int compare(node node0, node node1)
{
return node0.key - node1.key;
}
}
// method to add an edge
// between two vertices
void addEdge(Graph graph, int src, int dest, int weight)
{
node1 node0 = new node1(dest, weight);
node1 node = new node1(src, weight);
1603
Chapter 238. Prim’s MST for Adjacency List Representation Greedy Algo-6
graph.adj[src].addLast(node0);
graph.adj[dest].addLast(node);
}
// method used to find the mst
void prims_mst(Graph graph)
{
// Whether a vertex is in PriorityQueue or not
Boolean[] mstset = new Boolean[graph.V];
node[] e = new node[graph.V];
// Stores the parents of a vertex
int[] parent = new int[graph.V];
for (int o = 0; o < graph.V; o++)
e[o] = new node();
for (int o = 0; o < graph.V; o++) {
// Initialize to false
mstset[o] = false;
// Initialize key values to infinity
e[o].key = Integer.MAX_VALUE;
e[o].vertex = o;
parent[o] = -1;
}
// Include the source vertex in mstset
mstset[0] = true;
// Set key value to 0
// so that it is extracted first
// out of PriorityQueue
e[0].key = 0;
// PriorityQueue
PriorityQueue<node> queue = new PriorityQueue<>(graph.V, new comparator());
for (int o = 0; o < graph.V; o++)
queue.add(e[o]);
// Loops until the PriorityQueue is not empty
while (!queue.isEmpty()) {
// Extracts a node with min key value
node node0 = queue.poll();
1604
Chapter 238. Prim’s MST for Adjacency List Representation Greedy Algo-6
// Include that node into mstset
mstset[node0.vertex] = true;
// For all adjacent vertex of the extracted vertex V
for (node1 iterator : graph.adj[node0.vertex]) {
// If V is in PriorityQueue
if (mstset[iterator.dest] == false) {
// If the key value of the adjacent vertex is
// more than the extracted key
// update the key value of adjacent vertex
// to update first remove and add the updated vertex
if (e[iterator.dest].key > iterator.weight) {
queue.remove(e[iterator.dest]);
e[iterator.dest].key = iterator.weight;
queue.add(e[iterator.dest]);
parent[iterator.dest] = node0.vertex;
}
}
}
}
// Prints the vertex pair of mst
for (int o = 1; o < graph.V; o++)
System.out.println(parent[o] + " "
+ "-"
+ " " + o);
}
public static void main(String[] args)
{
int V = 9;
Graph graph = new Graph(V);
prims e = new prims();
e.addEdge(graph, 0, 1, 4);
e.addEdge(graph, 0, 7, 8);
e.addEdge(graph, 1, 2, 8);
e.addEdge(graph, 1, 7, 11);
e.addEdge(graph, 2, 3, 7);
e.addEdge(graph, 2, 8, 2);
e.addEdge(graph, 2, 5, 4);
e.addEdge(graph, 3, 4, 9);
e.addEdge(graph, 3, 5, 14);
e.addEdge(graph, 4, 5, 10);
1605
Chapter 238. Prim’s MST for Adjacency List Representation Greedy Algo-6
e.addEdge(graph, 5, 6, 2);
e.addEdge(graph, 6, 7, 1);
e.addEdge(graph, 6, 8, 6);
e.addEdge(graph, 7, 8, 7);
// Method invoked
e.prims_mst(graph);
}
}
// This code is contributed by Vikash Kumar Dubey
Python
1606
Chapter 238. Prim’s MST for Adjacency List Representation Greedy Algo-6
smallest = left
if right < self.size and self.array[right][1] < \
self.array[smallest][1]:
smallest = right
# The nodes to be swapped in min heap
# if idx is not smallest
if smallest != idx:
# Swap positions
self.pos[ self.array[smallest][0] ] = idx
self.pos[ self.array[idx][0] ] = smallest
# Swap nodes
self.swapMinHeapNode(smallest, idx)
self.minHeapify(smallest)
# Standard function to extract minimum node from heap
def extractMin(self):
# Return NULL wif heap is empty
if self.isEmpty() == True:
return
# Store the root node
root = self.array[0]
# Replace root node with last node
lastNode = self.array[self.size - 1]
self.array[0] = lastNode
# Update position of last node
self.pos[lastNode[0]] = 0
self.pos[root[0]] = self.size - 1
# Reduce heap size and heapify root
self.size -= 1
self.minHeapify(0)
return root
def isEmpty(self):
return True if self.size == 0 else False
def decreaseKey(self, v, dist):
1607
Chapter 238. Prim’s MST for Adjacency List Representation Greedy Algo-6
1608
Chapter 238. Prim’s MST for Adjacency List Representation Greedy Algo-6
1609
Chapter 238. Prim’s MST for Adjacency List Representation Greedy Algo-6
# Traverse through all adjacent vertices of u
# (the extracted vertex) and update their
# distance values
for pCrawl in self.graph[u]:
v = pCrawl[0]
# If shortest distance to v is not finalized
# yet, and distance to v through u is less than
# its previously calculated distance
if minHeap.isInMinHeap(v) and pCrawl[1] < key[v]:
key[v] = pCrawl[1]
parent[v] = u
# update distance value in min heap also
minHeap.decreaseKey(v, key[v])
printArr(parent, V)
# Driver program to test the above functions
graph = Graph(9)
graph.addEdge(0, 1, 4)
graph.addEdge(0, 7, 8)
graph.addEdge(1, 2, 8)
graph.addEdge(1, 7, 11)
graph.addEdge(2, 3, 7)
graph.addEdge(2, 8, 2)
graph.addEdge(2, 5, 4)
graph.addEdge(3, 4, 9)
graph.addEdge(3, 5, 14)
graph.addEdge(4, 5, 10)
graph.addEdge(5, 6, 2)
graph.addEdge(6, 7, 1)
graph.addEdge(6, 8, 6)
graph.addEdge(7, 8, 7)
graph.PrimMST()
# This code is contributed by Divyanshu Mehta
Output:
0 - 1
5 - 2
2 - 3
3 - 4
6 - 5
1610
Chapter 238. Prim’s MST for Adjacency List Representation Greedy Algo-6
7 - 6
0 - 7
2 - 8
Time Complexity: The time complexity of the above code/algorithm looks O(V^2) as
there are two nested while loops. If we take a closer look, we can observe that the statements
in inner loop are executed O(V+E) times (similar to BFS). The inner loop has decreaseKey()
operation which takes O(LogV) time. So overall time complexity is O(E+V)*O(LogV) which
is O((E+V)*LogV) = O(ELogV) (For a connected graph, V = O(E))
References:
Introduction to Algorithms by Clifford Stein, Thomas H. Cormen, Charles E. Leiserson,
Ronald L.
http://en.wikipedia.org/wiki/Prim’s_algorithm
This article is compiled by Aashish Barnwal and reviewed by GeeksforGeeks team. Please
write comments if you find anything incorrect, or you want to share more information about
the topic discussed above.
Improved By : VikashDubey, Sumon Nath
Source
https://www.geeksforgeeks.org/prims-mst-for-adjacency-list-representation-greedy-algo-6/
1611
Chapter 239
Print all paths from a given source to a destination using BFS - GeeksforGeeks
Given a directed graph, a source vertex ‘src’ and a destination vertex ‘dst’, print all paths
from given ‘src’ to ‘dst’.
Consider the following directed graph. Let the src be 2 and dst be 3. There are 3 different
paths from 2 to 3.
We have already discussed Print all paths from a given source to a destination using DFS.
Below is BFS based solution.
Algorithm :
1612
Chapter 239. Print all paths from a given source to a destination using BFS
1613
Chapter 239. Print all paths from a given source to a destination using BFS
// path vector to store the current path
vector<int> path;
path.push_back(src);
q.push(path);
while (!q.empty()) {
path = q.front();
q.pop();
int last = path[path.size() - 1];
// if last vertex is the desired destination
// then print the path
if (last == dst)
printpath(path);
// traverse to all the nodes connected to
// current vertex and push new path to queue
for (int i = 0; i < g[last].size(); i++) {
if (isNotVisited(g[last][i], path)) {
vector<int> newpath(path);
newpath.push_back(g[last][i]);
q.push(newpath);
}
}
}
}
// driver program
int main()
{
vector<vector<int> > g;
// number of vertices
int v = 4;
g.resize(4);
// construct a graph
g[0].push_back(3);
g[0].push_back(1);
g[0].push_back(2);
g[1].push_back(3);
g[2].push_back(0);
g[2].push_back(1);
int src = 2, dst = 3;
cout << "path from src " << src
<< " to dst " << dst << " are \n";
// function for finding the paths
1614
Chapter 239. Print all paths from a given source to a destination using BFS
Output:
Source
https://www.geeksforgeeks.org/print-paths-given-source-destination-using-bfs/
1615
Chapter 240
1616
Chapter 240. Print all the cycles in an undirected graph
In the above diagram, the cycles have been marked with dark green color. The output for
the above will be
1st cycle: 3 5 4 6
2nd cycle: 11 12 13
Approach: Using the graph coloring method, mark all the vertex of the different cycles
with unique numbers. Once the graph traversal is completed, push all the similar marked
numbers to an adjacency list and print the adjacency list accordingly. Given below is the
algorithm:
1617
Chapter 240. Print all the cycles in an undirected graph
• Once Dfs is completed, iterate for the edges and push the same marked number edges
to another adjacency list.
• Iterate in the another adjacency list and print the vertex cycle-number wise.
1618
Chapter 240. Print all the cycles in an undirected graph
color[u] = 1;
// simple dfs on graph
for (int v : graph[u]) {
// if it has not been visited previously
if (v == par[u]) {
continue;
}
dfs_cycle(v, u, color, mark, par, cyclenumber);
}
// completely visited.
color[u] = 2;
}
// add the edges to the graph
void addEdge(int u, int v)
{
graph[u].push_back(v);
graph[v].push_back(u);
}
// Function to print the cycles
void printCycles(int edges, int mark[], int& cyclenumber)
{
// push the edges that into the
// cycle adjacency list
for (int i = 1; i <= edges; i++) {
if (mark[i] != 0)
cycles[mark[i]].push_back(i);
}
// print all the vertex with same cycle
for (int i = 1; i <= cyclenumber; i++) {
// Print the i-th cycle
cout << "Cycle Number " << i << ": ";
for (int x : cycles[i])
cout << x << " ";
cout << endl;
}
}
// Driver Code
int main()
{
1619
Chapter 240. Print all the cycles in an undirected graph
Output:
Cycle Number 1: 3 4 5 6
Cycle Number 2: 11 12 13
Time Complexity: O(N + M), where N is number of vertex and M is the number of
edges.
Auxiliary Space: O(N + M)
Source
https://www.geeksforgeeks.org/print-all-the-cycles-in-an-undirected-graph/
1620
Chapter 241
1621
Chapter 241. Print the DFS traversal step-wise (Backtracking also)
Note: In this above diagram the weight between the edges has just been added, it does not
have any role in DFS-traversal
Approach: DFS with Backtracking will be used here. First, visit every node using DFS
simultaneously and keep track of the previously used edge and the parent node. If a node
comes whose all the adjacent node has been visited, backtrack using the last used edge and
print the nodes. Continue the steps and at every step, the parent node will become the
present node. Continue the above steps to find the complete DFS traversal of the graph.
Below is the implementation of the above approach:
1622
Chapter 241. Print the DFS traversal step-wise (Backtracking also)
1623
Chapter 241. Print the DFS traversal step-wise (Backtracking also)
visited[i] = false;
// call the function
dfsUtil(0, node, visited, road_used, -1, 0);
}
// Function to insert edges in Graph
void insertEdge(int u, int v)
{
adj[u].push_back(v);
adj[v].push_back(u);
}
// Driver Code
int main()
{
// number of nodes and edges in the graph
int node = 11, edge = 13;
// Function call to create the graph
insertEdge(0, 1);
insertEdge(0, 2);
insertEdge(1, 5);
insertEdge(1, 6);
insertEdge(2, 4);
insertEdge(2, 9);
insertEdge(6, 7);
insertEdge(6, 8);
insertEdge(7, 8);
insertEdge(2, 3);
insertEdge(3, 9);
insertEdge(3, 10);
insertEdge(9, 10);
// Call the function to print
dfs(node);
return 0;
}
Output:
0 1 5 1 6 7 8 7 6 1 0 2 4 2 9 3 10
Source
https://www.geeksforgeeks.org/print-the-dfs-traversal-step-wise-backtracking-also/
1624
Chapter 242
The implementations discussed above only find shortest distances, but do not print paths.
In this post printing of paths is discussed.
Output should be
Vertex Distance Path
0 -> 1 4 0 1
0 -> 2 12 0 1 2
0 -> 3 19 0 1 2 3
0 -> 4 21 0 7 6 5 4
0 -> 5 11 0 7 6 5
0 -> 6 9 0 7 6
0 -> 7 8 0 7
0 -> 8 14 0 1 2 8
1625
Chapter 242. Printing Paths in Dijkstra’s Shortest Path Algorithm
The idea is to create a separate array parent[]. Value of parent[v] for a vertex v stores parent
vertex of v in shortest path tree. Parent of root (or source vertex) is -1. Whenever we find
shorter path through a vertex u, we make u as parent of current vertex.
Once we have parent array constructed, we can print path using below recursive function.
printPath(parent, parent[j]);
1626
Chapter 242. Printing Paths in Dijkstra’s Shortest Path Algorithm
return min_index;
}
// Function to print shortest
// path from source to j
// using parent array
void printPath(int parent[], int j)
{
// Base Case : If j is source
if (parent[j] == - 1)
return;
printPath(parent, parent[j]);
printf("%d ", j);
}
// A utility function to print
// the constructed distance
// array
int printSolution(int dist[], int n,
int parent[])
{
int src = 0;
printf("Vertex\t Distance\tPath");
for (int i = 1; i < V; i++)
{
printf("\n%d -> %d \t\t %d\t\t%d ",
src, i, dist[i], src);
printPath(parent, i);
}
}
// Funtion that implements Dijkstra's
// single source shortest path
// algorithm for a graph represented
// using adjacency matrix representation
void dijkstra(int graph[V][V], int src)
{
// The output array. dist[i]
// will hold the shortest
// distance from src to i
int dist[V];
// sptSet[i] will true if vertex
1627
Chapter 242. Printing Paths in Dijkstra’s Shortest Path Algorithm
1628
Chapter 242. Printing Paths in Dijkstra’s Shortest Path Algorithm
// dist[v]
if (!sptSet[v] && graph[u][v] &&
dist[u] + graph[u][v] < dist[v])
{
parent[v] = u;
dist[v] = dist[u] + graph[u][v];
}
}
// print the constructed
// distance array
printSolution(dist, V, parent);
}
// Driver Code
int main()
{
// Let us create the example
// graph discussed above
int graph[V][V] = {{0, 4, 0, 0, 0, 0, 0, 8, 0},
{4, 0, 8, 0, 0, 0, 0, 11, 0},
{0, 8, 0, 7, 0, 4, 0, 0, 2},
{0, 0, 7, 0, 9, 14, 0, 0, 0},
{0, 0, 0, 9, 0, 10, 0, 0, 0},
{0, 0, 4, 0, 10, 0, 2, 0, 0},
{0, 0, 0, 14, 0, 2, 0, 1, 6},
{8, 11, 0, 0, 0, 0, 1, 0, 7},
{0, 0, 2, 0, 0, 0, 6, 7, 0}
};
dijkstra(graph, 0);
return 0;
}
Java
1629
Chapter 242. Printing Paths in Dijkstra’s Shortest Path Algorithm
1630
Chapter 242. Printing Paths in Dijkstra’s Shortest Path Algorithm
1631
Chapter 242. Printing Paths in Dijkstra’s Shortest Path Algorithm
int[] parents)
{
int nVertices = distances.length;
System.out.print("Vertex\t Distance\tPath");
for (int vertexIndex = 0;
vertexIndex < nVertices;
vertexIndex++)
{
if (vertexIndex != startVertex)
{
System.out.print("\n" + startVertex + " -> ");
System.out.print(vertexIndex + " \t\t ");
System.out.print(distances[vertexIndex] + "\t\t");
printPath(vertexIndex, parents);
}
}
}
// Function to print shortest path
// from source to currentVertex
// using parents array
private static void printPath(int currentVertex,
int[] parents)
{
// Base case : Source node has
// been processed
if (currentVertex == NO_PARENT)
{
return;
}
printPath(parents[currentVertex], parents);
System.out.print(currentVertex + " ");
}
// Driver Code
public static void main(String[] args)
{
int[][] adjacencyMatrix = { { 0, 4, 0, 0, 0, 0, 0, 8, 0 },
{ 4, 0, 8, 0, 0, 0, 0, 11, 0 },
{ 0, 8, 0, 7, 0, 4, 0, 0, 2 },
{ 0, 0, 7, 0, 9, 14, 0, 0, 0 },
{ 0, 0, 0, 9, 0, 10, 0, 0, 0 },
{ 0, 0, 4, 0, 10, 0, 2, 0, 0 },
{ 0, 0, 0, 14, 0, 2, 0, 1, 6 },
{ 8, 11, 0, 0, 0, 0, 1, 0, 7 },
{ 0, 0, 2, 0, 0, 0, 6, 7, 0 } };
1632
Chapter 242. Printing Paths in Dijkstra’s Shortest Path Algorithm
dijkstra(adjacencyMatrix, 0);
}
}
// This code is contributed by Harikrishnan Rajan
Python
1633
Chapter 242. Printing Paths in Dijkstra’s Shortest Path Algorithm
# A utility function to print
# the constructed distance
# array
def printSolution(self, dist, parent):
src = 0
print("Vertex \t\tDistance from Source\tPath")
for i in range(1, len(dist)):
print("\n%d --> %d \t\t%d \t\t\t\t\t" % (src, i, dist[i])),
self.printPath(parent,i)
'''Function that implements Dijkstra's single source shortest path
algorithm for a graph represented using adjacency matrix
representation'''
def dijkstra(self, graph, src):
row = len(graph)
col = len(graph[0])
# The output array. dist[i] will hold
# the shortest distance from src to i
# Initialize all distances as INFINITE
dist = [float("Inf")] * row
#Parent array to store
# shortest path tree
parent = [-1] * row
# Distance of source vertex
# from itself is always 0
dist[src] = 0
# Add all vertices in queue
queue = []
for i in range(row):
queue.append(i)
#Find shortest path for all vertices
while queue:
# Pick the minimum dist vertex
# from the set of vertices
# still in queue
u = self.minDistance(dist,queue)
# remove min element
queue.remove(u)
1634
Chapter 242. Printing Paths in Dijkstra’s Shortest Path Algorithm
# Update dist value and parent
# index of the adjacent vertices of
# the picked vertex. Consider only
# those vertices which are still in
# queue
for i in range(col):
'''Update dist[i] only if it is in queue, there is
an edge from u to i, and total weight of path from
src to i through u is smaller than current value of
dist[i]'''
if graph[u][i] and i in queue:
if dist[u] + graph[u][i] < dist[i]:
dist[i] = dist[u] + graph[u][i]
parent[i] = u
# print the constructed distance array
self.printSolution(dist,parent)
g= Graph()
graph = [[0, 4, 0, 0, 0, 0, 0, 8, 0],
[4, 0, 8, 0, 0, 0, 0, 11, 0],
[0, 8, 0, 7, 0, 4, 0, 0, 2],
[0, 0, 7, 0, 9, 14, 0, 0, 0],
[0, 0, 0, 9, 0, 10, 0, 0, 0],
[0, 0, 4, 14, 10, 0, 2, 0, 0],
[0, 0, 0, 0, 0, 2, 0, 1, 6],
[8, 11, 0, 0, 0, 0, 1, 0, 7],
[0, 0, 2, 0, 0, 0, 6, 7, 0]
]
#Print the solution
g.dijkstra(graph,0)
#This code is contributed by Neelam Yadav
Output:
1635
Chapter 242. Printing Paths in Dijkstra’s Shortest Path Algorithm
0 -> 6 9 0 7 6
0 -> 7 8 0 7
0 -> 8 14 0 1 2 8
This article is contributed by Aditya Goel. Please write comments if you find anything
incorrect, or you want to share more information about the topic discussed above
Improved By : rhari
Source
https://www.geeksforgeeks.org/printing-paths-dijkstras-shortest-path-algorithm/
1636
Chapter 243
The above graph has two cycles of length 4 and 3, the product of cycle lengths
is 12.
1637
Chapter 243. Product of lengths of all cycles in an undirected graph
Example 2:
The above graph has two cycles of length 4 and 3, the product of cycle lengths
is 12.
Approach: Using the graph coloring method, mark all the vertex of the different cycles
with unique numbers. Once the graph traversal is completed, push all the similar marked
numbers to an adjacency list and print the adjacency list accordingly. Given below is the
algorithm:
• Whenever there is a partially visited vertex, backtrack till the current vertex is reached
and mark all of them with cycle numbers. Once all the vertexes are marked, increase
the cycle number.
1638
Chapter 243. Product of lengths of all cycles in an undirected graph
• Once Dfs is completed, iterate for the edges and push the same marked number edges
to another adjacency list.
• Iterate in the another adjacency list, and keep the count of number of vertex in a cycle
using map and cycle numbers
• Iterate for cycle numbers, and multiply the lengths to get the final product which will
be the answer.
1639
Chapter 243. Product of lengths of all cycles in an undirected graph
return;
}
par[u] = p;
// partially visited.
color[u] = 1;
// simple dfs on graph
for (int v : graph[u]) {
// if it has not been visited previously
if (v == par[u]) {
continue;
}
dfs_cycle(v, u, color, mark, par, cyclenumber);
}
// completely visited.
color[u] = 2;
}
// add the edges to the graph
void addEdge(int u, int v)
{
graph[u].push_back(v);
graph[v].push_back(u);
}
// Function to print the cycles
int productLength(int edges, int mark[], int& cyclenumber)
{
unordered_map<int, int> mp;
// push the edges that into the
// cycle adjacency list
for (int i = 1; i <= edges; i++) {
if (mark[i] != 0)
mp[mark[i]]++;
}
int cnt = 1;
// prodcut all the length of cycles
for (int i = 1; i <= cyclenumber; i++) {
cnt = cnt * mp[i];
}
if (cyclenumber == 0)
cnt = 0;
1640
Chapter 243. Product of lengths of all cycles in an undirected graph
return cnt;
}
// Driver Code
int main()
{
// add edges
addEdge(1, 2);
addEdge(2, 3);
addEdge(3, 4);
addEdge(4, 6);
addEdge(4, 7);
addEdge(5, 6);
addEdge(3, 5);
addEdge(7, 8);
addEdge(6, 10);
addEdge(5, 9);
addEdge(10, 11);
addEdge(11, 12);
addEdge(11, 13);
addEdge(12, 13);
// arrays required to color the
// graph, store the parent of node
int color[N];
int par[N];
// mark with unique numbers
int mark[N];
// store the numbers of cycle
int cyclenumber = 0;
int edges = 13;
// call DFS to mark the cycles
dfs_cycle(1, 0, color, mark, par, cyclenumber);
// function to print the cycles
cout << productLength(edges, mark, cyclenumber);
return 0;
}
Output:
12
1641
Chapter 243. Product of lengths of all cycles in an undirected graph
Source
https://www.geeksforgeeks.org/product-of-lengths-of-all-cycles-in-an-undirected-graph/
1642
Chapter 244
If the 2nd condition is only satisfied then the problem is called NP-Hard.
But it is not possible to reduce every NP problem into another NP problem to show its
NP-Completeness all the time. That is why if we want to show a problem is NP-Complete
we just show that the problem is in NP and any NP-Complete problem is reducible to that
then we are done, i.e. if B is NP-Complete and for C in NP, then C is NP-
Complete.
We have to show Hamiltonian Path is NP-Complete. Hamiltonian Path or HAMPATH
in a directed graph G is a directed path that goes through each node exactly once. We Con-
sider the problem of testing whether a directed graph contain a Hamiltonian path connecting
two specified nodes, i.e.
1643
Chapter 244. Proof that Hamiltonian Path is NP-Complete
For each 3-cnf formula we will show how to build graph G with s and t, where a Hamil-
tonian path exists between s and t iff is satisfiable.
We start with a 3-cnf formula containing k clauses,
1644
Chapter 244. Proof that Hamiltonian Path is NP-Complete
1645
Chapter 244. Proof that Hamiltonian Path is NP-Complete
The following figure depicts the global structure of G. It shows all the elements of G and
their relationships, except the edges that represent the relationship of the variables to the
clauses that contain them.
1646
Chapter 244. Proof that Hamiltonian Path is NP-Complete
1647
Chapter 244. Proof that Hamiltonian Path is NP-Complete
Each diamond structure contains a horizontal row of nodes connected by edges running in
both directions. The horizontal row contains 2k nodes (as 2 nodes for each clause) plus, k-1
extra nodes in between every two nodes for a clause plus, 2 nodes on the ends belonging to
the diamonds; total 3k+1 nodes. Following diagram gives a clear picture.
If variable appears in clause , we add the following two edges from the jth pair in
the ith diamoond to the jth clause node.
1648
Chapter 244. Proof that Hamiltonian Path is NP-Complete
If appears in clause c_j, we add two edges from the jth pair in the ith diamond to the
jth clause node, as in the following figure.
1649
Chapter 244. Proof that Hamiltonian Path is NP-Complete
After we add all the edges corresponding to each occurrence of or in each clause,
a Hamiltonian path exists from s to t and conversely, if such a path exists is satisfiable.
1650
Chapter 244. Proof that Hamiltonian Path is NP-Complete
So far this path covers all the nodes in G except the clause nodes. We can easily include
them by adding detours at the horizontal nodes. In each clause, we select one of the literals
assigned TRUE, by satisfying assignment.
If we selected in clause , we can detour at the jth pair in the ith diamond. Doing so
is possible because must be TRUE, so the path zig-zags from left to right through the
corresponding diamond. Hence the edges to the node are in the correct order to allow
a detour and return.
Similarly, if we selected in clause , we can detour at the jth pair in the ith
diamond because must be FALSE, so the path zag-zigs from right to left through the
corresponding diamond. Hence the edges to he node are again in the correct order to
allow a detour and return. Every time one detour is taken if each literal in clause provides
an option for detour. Thus each node is visited exactly once and thus Hamiltonian Path is
constructed.
For the reverse direction, if G has a Hamiltonian path from s to t, we demonstrate a
satisfying assignment for . If the Hamiltonian path is normal i.e. it goes through
diamonds in order from top to bottom node except the detour for the closure nodes; we
can easily obtain the satisfying assignment. If the path zig-zags in diamond we assign the
variables as TRUE and if it zag-zigs then assign it FALSE. Because every node appears
on the path by observing how the detour is taken we may determine corresponding TRUE
variables.
1651
Chapter 244. Proof that Hamiltonian Path is NP-Complete
All that remains to be shown that Hamiltonian path must be normal means the path enters
a clause from one diamond but returns to another like in the following figure.
The path goes from node to c; but instead of returning to in the same diamond,
1652
Chapter 244. Proof that Hamiltonian Path is NP-Complete
Source
https://www.geeksforgeeks.org/proof-hamiltonian-path-np-complete/
1653
Chapter 245
Push-Relabel Algorithm
Push-Relabel approach is the more efficient than Ford-Fulkerson algorithm. In this post,
Goldberg’s “generic” maximum-flow algorithm is discussed that runs in O(V2 E) time. This
1654
Chapter 245. Push Relabel Algorithm Set 1 (Introduction and Illustration)
time complexity is better than O(E2 V) which is time complexity of Edmond-Karp algorithm
(a BFS based implementation of Ford-Fulkerson). There exist a push-relabel approach based
algorithm that works in O(V3 ) which is even better than the one discussed here.
Similarities with Ford Fulkerson
• Push-relabel algorithm works in a more localized. Rather than examining the entire
residual network to find an augmenting path, push-relabel algorithms work on one
vertex at a time (Source : CLRS Book).
• In Ford-Fulkerson, net difference between total outflow and total inflow for every vertex
(Except source and sink) is maintained 0. Push-Relabel algorithm allows inflow to
exceed the outflow before reaching the final flow. In final flow, the net difference is 0
for all except source and sink.
• Time complexity wise more efficient.
The intuition behind the push-relabel algorithm (considering a fluid flow problem) is that
we consider edges as water pipes and nodes are joints. The source is considered to be at
the highest level and it sends water to all adjacent nodes. Once a node has excess water, it
pushes water to a smaller height node. If water gets locally trapped at a vertex, the vertex
is Relabeled which means its height is increased.
Following are some useful facts to consider before we proceed to algorithm.
• Each vertex has associated to it a height variable and a Excess Flow. Height is used
to determine whether a vertex can push flow to an adjacent or not (A vertex can
push flow only to a smaller height vertex). Excess flow is the difference of total flow
coming into the vertex minus the total flow going out of the vertex.
• Like Ford Fulkerson. each edge has associated to it a flow (which indicates current
flow) and a capacity
Push-Relabel Algorithm
1) Initialize PreFlow : Initialize Flows and Heights
1655
Chapter 245. Push Relabel Algorithm Set 1 (Introduction and Illustration)
Preflow()
1) Initialize height and flow of every vertex as 0.
2) Initialize height of source vertex equal to total
number of vertices in graph.
3) Initialize flow of every edge as 0.
4) For all vertices adjacent to source s, flow and
excess flow is equal to capacity initially.
2. Push() is used to make the flow from a node which has excess flow. If a vertex has
excess flow and there is an adjacent with smaller height (in residual graph), we push
the flow from the vertex to the adjacent with lower height. The amount of pushed
flow through the pipe (edge) is equal to the minimum of excess flow and capacity of
edge.
3. Relabel() operation is used when a vertex has excess flow and none of its adjacent
is at lower height. We basically increase height of the vertex so that we can perform
push(). To increase height, we pick the minimum height adjacent (in residual graph,
i.e., an adjacent to whom we can add flow) and add 1 to it.
Note that above operations are performed on residual graph (like Ford-Fulkerson).
Illustration:
Before we proceed to below example, we need to make sure that we understand residual
graph (See this for more details of residual graph). Residual graph is different from graphs
shown.
Whenever we push or add a flow from a vertex u to v, we do following updates in residual
graph :
1) We subtract the flow from capacity of edge from u to v. If capacity of an edge becomes
0, then the edge no longer exists in residual graph.
2) We add flow to the capacity of edge from v to u.
1656
Chapter 245. Push Relabel Algorithm Set 1 (Introduction and Illustration)
In original graph
3/10
u ---------> v
3 is current flow from u to v and
10 is capacity of edge from u to v.
3
u <--------- v
2. After PreFlow operation. In residual graph, there is an edge from A to S with capacity
3 and no edge from S to A.
3. The highlighted vertex is relabeled (height becomes 1) as it has excess flow and there
is no adjacent with smaller height. The new height is equal to minimum of heights of
adjacent plus 1. In residual graph, there are two adjacent of vertex A, one is S and
other is B. Height of S is 4 and height of B is 0. Minimum of these two heights is 0.
We take the minimum and add 1 to it.
1657
Chapter 245. Push Relabel Algorithm Set 1 (Introduction and Illustration)
4. The highlighted vertex has excess flow and there is an adjacent with lower height,
so push() happens. Excess flow of vertex A is 2 and capacity of edge (A, B) is 1.
Therefore, the amount of pushed flow is 1 (minimum of two values).
5. The highlighted vertex is relabeled (height becomes 1) as it has excess flow and there
is no adjacent with smaller height.
6. The highlighted vertex has excess flow and there is an adjacent with lower height, so
flow() is pushed from B to T.
7. The highlighted vertex is relabeled (height becomes 5) as it has excess flow and there
is no adjacent with smaller height.
1658
Chapter 245. Push Relabel Algorithm Set 1 (Introduction and Illustration)
8. The highlighted vertex has excess flow and there is an adjacent with lower height, so
push() happens.
9. The highlighted vertex is relabeled (height is increased by 1) as it has excess flow and
there is no adjacent with smaller height.
Source
https://www.geeksforgeeks.org/push-relabel-algorithm-set-1-introduction-and-illustration/
1659
Chapter 246
Push-Relabel Algorithm
1) Initialize PreFlow : Initialize Flows and Heights
1660
Chapter 246. Push Relabel Algorithm Set 2 (Implementation)
Preflow()
1) Initialize height and flow of every vertex as 0.
2) Initialize height of source vertex equal to total
number of vertices in graph.
3) Initialize flow of every edge as 0.
4) For all vertices adjacent to source s, flow and
excess flow is equal to capacity initially.
2. Push() is used to make the flow from a node which has excess flow. If a vertex has
excess flow and there is an adjacent with smaller height (in residual graph), we push
the flow from the vertex to the adjacent with lower height. The amount of pushed
flow through the pipe (edge) is equal to the minimum of excess flow and capacity of
edge.
3. Relabel() operation is used when a vertex has excess flow and none of its adjacent
is at lower height. We basically increase height of the vertex so that we can perform
push(). To increase height, we pick the minimum height adjacent (in residual graph,
i.e., an adjacent to whom we can add flow) and add 1 to it.
Implementation:
The following implementation uses below structure for representing a flow network.
struct Vertex
{
int h; // Height of node
int e_flow; // Excess Flow
}
struct Edge
{
int u, v; // Edge is from u to v
1661
Chapter 246. Push Relabel Algorithm Set 2 (Implementation)
class Graph
{
Edge edge[]; // Array of edges
Vertex ver[]; // Array of vertices
}
The below code uses given graph itself as a flow network and residual graph. We have not
created a separate graph for residual graph and have used the same graph for simplicity.
1662
Chapter 246. Push Relabel Algorithm Set 2 (Implementation)
};
// To represent a flow network
class Graph
{
int V; // No. of vertices
vector<Vertex> ver;
vector<Edge> edge;
// Function to push excess flow from u
bool push(int u);
// Function to relabel a vertex u
void relabel(int u);
// This function is called to initialize
// preflow
void preflow(int s);
// Function to reverse edge
void updateReverseEdgeFlow(int i, int flow);
public:
Graph(int V); // Constructor
// function to add an edge to graph
void addEdge(int u, int v, int w);
// returns maximum flow from s to t
int getMaxFlow(int s, int t);
};
Graph::Graph(int V)
{
this->V = V;
// all vertices are initialized with 0 height
// and 0 excess flow
for (int i = 0; i < V; i++)
ver.push_back(Vertex(0, 0));
}
void Graph::addEdge(int u, int v, int capacity)
{
// flow is initialized with 0 for all edge
edge.push_back(Edge(0, capacity, u, v));
}
1663
Chapter 246. Push Relabel Algorithm Set 2 (Implementation)
void Graph::preflow(int s)
{
// Making h of source Vertex equal to no. of vertices
// Height of other vertices is 0.
ver[s].h = ver.size();
//
for (int i = 0; i < edge.size(); i++)
{
// If current edge goes from source
if (edge[i].u == s)
{
// Flow is equal to capacity
edge[i].flow = edge[i].capacity;
// Initialize excess flow for adjacent v
ver[edge[i].v].e_flow += edge[i].flow;
// Add an edge from v to s in residual graph with
// capacity equal to 0
edge.push_back(Edge(-edge[i].flow, 0, edge[i].v, s));
}
}
}
// returns index of overflowing Vertex
int overFlowVertex(vector<Vertex>& ver)
{
for (int i = 1; i < ver.size() - 1; i++)
if (ver[i].e_flow > 0)
return i;
// -1 if no overflowing Vertex
return -1;
}
// Update reverse flow for flow added on ith Edge
void Graph::updateReverseEdgeFlow(int i, int flow)
{
int u = edge[i].v, v = edge[i].u;
for (int j = 0; j < edge.size(); j++)
{
if (edge[j].v == v && edge[j].u == u)
{
edge[j].flow -= flow;
return;
}
1664
Chapter 246. Push Relabel Algorithm Set 2 (Implementation)
}
// adding reverse Edge in residual graph
Edge e = Edge(0, flow, u, v);
edge.push_back(e);
}
// To push flow from overflowing vertex u
bool Graph::push(int u)
{
// Traverse through all edges to find an adjacent (of u)
// to which flow can be pushed
for (int i = 0; i < edge.size(); i++)
{
// Checks u of current edge is same as given
// overflowing vertex
if (edge[i].u == u)
{
// if flow is equal to capacity then no push
// is possible
if (edge[i].flow == edge[i].capacity)
continue;
// Push is only possible if height of adjacent
// is smaller than height of overflowing vertex
if (ver[u].h > ver[edge[i].v].h)
{
// Flow to be pushed is equal to minimum of
// remaining flow on edge and excess flow.
int flow = min(edge[i].capacity - edge[i].flow,
ver[u].e_flow);
// Reduce excess flow for overflowing vertex
ver[u].e_flow -= flow;
// Increase excess flow for adjacent
ver[edge[i].v].e_flow += flow;
// Add residual flow (With capacity 0 and negative
// flow)
edge[i].flow += flow;
updateReverseEdgeFlow(i, flow);
return true;
}
}
}
1665
Chapter 246. Push Relabel Algorithm Set 2 (Implementation)
return false;
}
// function to relabel vertex u
void Graph::relabel(int u)
{
// Initialize minimum height of an adjacent
int mh = INT_MAX;
// Find the adjacent with minimum height
for (int i = 0; i < edge.size(); i++)
{
if (edge[i].u == u)
{
// if flow is equal to capacity then no
// relabeling
if (edge[i].flow == edge[i].capacity)
continue;
// Update minimum height
if (ver[edge[i].v].h < mh)
{
mh = ver[edge[i].v].h;
// updating height of u
ver[u].h = mh + 1;
}
}
}
}
// main function for printing maximum flow of graph
int Graph::getMaxFlow(int s, int t)
{
preflow(s);
// loop untill none of the Vertex is in overflow
while (overFlowVertex(ver) != -1)
{
int u = overFlowVertex(ver);
if (!push(u))
relabel(u);
}
// ver.back() returns last Vertex, whose
// e_flow will be final maximum flow
return ver.back().e_flow;
}
1666
Chapter 246. Push Relabel Algorithm Set 2 (Implementation)
// Driver program to test above functions
int main()
{
int V = 6;
Graph g(V);
// Creating above shown flow network
g.addEdge(0, 1, 16);
g.addEdge(0, 2, 13);
g.addEdge(1, 2, 10);
g.addEdge(2, 1, 4);
g.addEdge(1, 3, 12);
g.addEdge(2, 4, 14);
g.addEdge(3, 2, 9);
g.addEdge(3, 5, 20);
g.addEdge(4, 3, 7);
g.addEdge(4, 5, 4);
// Initialize source and sink
int s = 0, t = 5;
cout << "Maximum flow is " << g.getMaxFlow(s, t);
return 0;
}
Output
Maximum flow is 23
The code in this article is contributed by Siddharth Lalwani and Utkarsh Trivedi.
Source
https://www.geeksforgeeks.org/push-relabel-algorithm-set-2-implementation/
1667
Chapter 247
Remove all outgoing edges except edge with minimum weight - GeeksforGeeks
Given a directed graph having n nodes. For each node, delete all the outgoing edges except
the outgoing edge with minimum weight. Apply this deletion operation for every node and
then print the final graph remained where each node of the graph has at most one outgoing
edge and that too with minimum weight.
Note: Here, graph is stored as Adjacency Matrix for ease.
Examples :
1668
Chapter 247. Remove all outgoing edges except edge with minimum weight
For every row of the adjacency matrix of graph keep the minimum element (except zero)
and make rest of all zero. Do this for every row of the input matrix. Finally, print the
resultant Matrix.
Example :
C++
1669
Chapter 247. Remove all outgoing edges except edge with minimum weight
1670
Chapter 247. Remove all outgoing edges except edge with minimum weight
Java
1671
Chapter 247. Remove all outgoing edges except edge with minimum weight
{
int min;
// Set empty edges
// to INT_MAX
for (int i = 0;
i < arr.length; i++)
for (int j = 0;
j < arr.length; j++)
if (arr[i][j] == 0)
arr[i][j] = Integer.MAX_VALUE;
// Finding minimum of each
// row and deleting rest
// of edges
for (int i = 0;
i < arr.length; i++)
{
// Find minimum
// element of row
min = minFn(arr[i]);
for (int j = 0;
j < arr.length; j++)
{
// If edge value is not
// min set it to zero,
// also edge value INT_MAX
// denotes that initially
// edge value was zero
if ((arr[i][j] != min) ||
(arr[i][j] == Integer.MAX_VALUE))
arr[i][j] = 0;
else
min = 0;
}
}
// Print result;
for (int i = 0;
i < arr.length; i++)
{
for (int j = 0;
j < arr.length; j++)
System.out.print(arr[i][j] + " ");
System.out.print("\n");
}
1672
Chapter 247. Remove all outgoing edges except edge with minimum weight
}
// Driver Code
public static void main(String[] args)
{
// Input Graph
int arr[][] = {{1, 2, 4, 0},
{0, 0, 0, 5},
{0, 2, 0, 3},
{0, 0, 0, 0}};
minimizeGraph(arr);
}
}
Output:
1 0 0 0
0 0 0 5
0 2 0 0
0 0 0 0
Source
https://www.geeksforgeeks.org/minimum-weighted-graph/
1673
Chapter 248
Illustration:
Let us understand with the following example:
1674
Chapter 248. Reverse Delete Algorithm for Minimum Spanning Tree
If we delete highest weight edge of weight 14, graph doesn’t become disconnected, so we
remove it.
1675
Chapter 248. Reverse Delete Algorithm for Minimum Spanning Tree
Edges in MST
(3, 4)
(0, 7)
(2, 3)
(2, 5)
(0, 1)
(5, 6)
(2, 8)
(6, 7)
Note : In case of same weight edges, we can pick any edge of the same weight edges.
Below is C++ implementation of above steps.
1676
Chapter 248. Reverse Delete Algorithm for Minimum Spanning Tree
1677
Chapter 248. Reverse Delete Algorithm for Minimum Spanning Tree
return true;
}
// This function assumes that edge (u, v)
// exists in graph or not,
void Graph::reverseDeleteMST()
{
// Sort edges in increasing order on basis of cost
sort(edges.begin(), edges.end());
int mst_wt = 0; // Initialize weight of MST
cout << "Edges in MST\n";
// Iterate through all sorted edges in
// decreasing order of weights
for (int i=edges.size()-1; i>=0; i--)
{
int u = edges[i].second.first;
int v = edges[i].second.second;
// Remove edge from undirected graph
adj[u].remove(v);
adj[v].remove(u);
// Adding the edge back if removing it
// causes disconnection. In this case this
// edge becomes part of MST.
if (isConnected() == false)
{
adj[u].push_back(v);
adj[v].push_back(u);
// This edge is part of MST
cout << "(" << u << ", " << v << ") \n";
mst_wt += edges[i].first;
}
}
cout << "Total weight of MST is " << mst_wt;
}
// Driver code
int main()
{
// create the graph given in above fugure
int V = 9;
1678
Chapter 248. Reverse Delete Algorithm for Minimum Spanning Tree
Graph g(V);
// making above shown graph
g.addEdge(0, 1, 4);
g.addEdge(0, 7, 8);
g.addEdge(1, 2, 8);
g.addEdge(1, 7, 11);
g.addEdge(2, 3, 7);
g.addEdge(2, 8, 2);
g.addEdge(2, 5, 4);
g.addEdge(3, 4, 9);
g.addEdge(3, 5, 14);
g.addEdge(4, 5, 10);
g.addEdge(5, 6, 2);
g.addEdge(6, 7, 1);
g.addEdge(6, 8, 6);
g.addEdge(7, 8, 7);
g.reverseDeleteMST();
return 0;
}
Output :
Edges in MST
(3, 4)
(0, 7)
(2, 3)
(2, 5)
(0, 1)
(5, 6)
(2, 8)
(6, 7)
Total weight of MST is 37
Notes :
References:
https://en.wikipedia.org/wiki/Reverse-delete_algorithm
1679
Chapter 248. Reverse Delete Algorithm for Minimum Spanning Tree
Source
https://www.geeksforgeeks.org/reverse-delete-algorithm-minimum-spanning-tree/
1680
Chapter 249
We can solve this problem by first thinking about 1-D solution, that is if a longest graph is
given, then the node which will minimize the height will be mid node if total node count is
odd or mid two node if total node count is even. This solution can be reached by following
approach – Start two pointers from both end of the path and move one step each time,
until pointers meet or one step away, at the end pointers will be at those nodes which will
minimize the height because we have divided the nodes evenly so height will be minimum.
Same approach can be applied to a general tree also. Start pointers from all leaf nodes and
move one step inside each time, keep combining pointers which overlap while moving, at the
end only one pointer will remain on some vertex or two pointers will remain at one distance
away. Those node represent the root of the vertex which will minimize the height of the
1681
Chapter 249. Roots of a tree which give minimum height
tree.
So we can have only one root or at max two root for minimum height depending on tree
structure as explained above. For implementation we will not use actual pointers instead
we’ll follow BFS like approach, In starting all leaf node are pushed into the queue, then
they are removed from tree, next new leaf node are pushed in queue, this procedure keeps
on going until we have only 1 or 2 node in our tree, which represent the result.
As we are accessing each node once, total time complexity of solution is O(n).
C++
// C++ program to find root which gives minimum height to tree
#include <bits/stdc++.h>
using namespace std;
// This class represents a undirected graph using adjacency list
// representation
class Graph
{
public:
int V; // No. of vertices
// Pointer to an array containing adjacency lists
list<int> *adj;
// Vector which stores degree of all vertices
vector<int> degree;
Graph(int V); // Constructor
void addEdge(int v, int w); // To add an edge
// function to get roots which give minimum height
vector<int> rootForMinimumHeight();
};
// Constructor of graph, initializes adjacency list and
// degree vector
Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V];
for (int i = 0; i < V; i++)
degree.push_back(0);
}
// addEdge method adds vertex to adjacency list and increases
// degree by 1
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w); // Add w to v’s list
1682
Chapter 249. Roots of a tree which give minimum height
1683
Chapter 249. Roots of a tree which give minimum height
Graph g(6);
g.addEdge(0, 3);
g.addEdge(1, 3);
g.addEdge(2, 3);
g.addEdge(4, 3);
g.addEdge(5, 4);
vector<int> res = g.rootForMinimumHeight();
for (int i = 0; i < res.size(); i++)
cout << res[i] << " ";
cout << endl;
}
Python
1684
Chapter 249. Roots of a tree which give minimum height
def rootForMinimumHeight(self):
from Queue import Queue
q = Queue()
# First enqueue all leaf nodes in queue
for i in range(self.V):
if self.degree[i] == 1:
q.put(i)
# loop until total vertex remains less than 2
while(self.V > 2):
for i in range(q.qsize()):
t = q.get()
self.V -=1
# for each neighbour, decrease its degree and
# if it become leaf, insert into queue
for j in self.adj[t]:
self.degree[j] -= 1
if self.degree[j] == 1:
q.put(j)
# Copying the result from queue to result vector
res = list()
while(q.qsize() > 0):
res.append(q.get())
return res
# Driver code to test above methods
g = Graph(6, addEdge, rootForMinimumHeight )
g.addEdge(0, 3)
g.addEdge(1, 3)
g.addEdge(2, 3)
g.addEdge(4, 3)
g.addEdge(5, 4)
res = g.rootForMinimumHeight()
for i in res:
print i,
# This code is contributed by Nikhil Kumar Singh(nickzuck_007)
Output:
1685
Chapter 249. Roots of a tree which give minimum height
3 4
Source
https://www.geeksforgeeks.org/roots-tree-gives-minimum-height/
1686
Chapter 250
Input:
mat[ROW][COL] = {{1, 0, 1, 1, 1, 1, 0, 1, 1, 1 },
{1, 0, 1, 0, 1, 1, 1, 0, 1, 1 },
{1, 1, 1, 0, 1, 1, 0, 1, 0, 1 },
{0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
{1, 1, 1, 0, 1, 1, 1, 0, 1, 0 },
{1, 0, 1, 1, 1, 1, 0, 1, 0, 0 },
{1, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{1, 0, 1, 1, 1, 1, 0, 1, 1, 1 },
{1, 1, 0, 0, 0, 0, 1, 0, 0, 1 }};
Source = {0, 0};
Destination = {3, 4};
Output:
Shortest Path is 11
1687
Chapter 250. Shortest path in a Binary Maze
3. We also maintain a Boolean array visited of same size as our input matrix and initialize
all its elements to false.
1688
Chapter 250. Shortest path in a Binary Maze
1689
Chapter 250. Shortest path in a Binary Maze
visited[row][col] = true;
queueNode Adjcell = { {row, col},
curr.dist + 1 };
q.push(Adjcell);
}
}
}
//return -1 if destination cannot be reached
return INT_MAX;
}
// Driver program to test above function
int main()
{
int mat[ROW][COL] =
{
{ 1, 0, 1, 1, 1, 1, 0, 1, 1, 1 },
{ 1, 0, 1, 0, 1, 1, 1, 0, 1, 1 },
{ 1, 1, 1, 0, 1, 1, 0, 1, 0, 1 },
{ 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
{ 1, 1, 1, 0, 1, 1, 1, 0, 1, 0 },
{ 1, 0, 1, 1, 1, 1, 0, 1, 0, 0 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 1, 1, 1, 1, 0, 1, 1, 1 },
{ 1, 1, 0, 0, 0, 0, 1, 0, 0, 1 }
};
Point source = {0, 0};
Point dest = {3, 4};
int dist = BFS(mat, source, dest);
if (dist != INT_MAX)
cout << "Shortest Path is " << dist ;
else
cout << "Shortest Path doesn't exist";
return 0;
}
Output :
Shortest Path is 11
This article is contributed by Aditya Goel. Please write comments if you find anything
incorrect, or you want to share more information about the topic discussed above
Improved By : Chinmay Singh
1690
Chapter 250. Shortest path in a Binary Maze
Source
https://www.geeksforgeeks.org/shortest-path-in-a-binary-maze/
1691
Chapter 251
1692
Chapter 251. Shortest Path in a weighted Graph where weight of an edge is 1 or 2
#include<bits/stdc++.h>
using namespace std;
// This class represents a directed graph using adjacency
// list representation
class Graph
{
int V; // No. of vertices
list<int> *adj; // adjacency lists
public:
Graph(int V); // Constructor
void addEdge(int v, int w, int weight); // adds an edge
// finds shortest path from source vertex ‘s’ to
// destination vertex ‘d’.
int findShortestPath(int s, int d);
// print shortest path from a source vertex ‘s’ to
// destination vertex ‘d’.
int printShortestPath(int parent[], int s, int d);
};
Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[2*V];
}
void Graph::addEdge(int v, int w, int weight)
{
// split all edges of weight 2 into two
// edges of weight 1 each. The intermediate
// vertex number is maximum vertex number + 1,
// that is V.
if (weight==2)
{
adj[v].push_back(v+V);
adj[v+V].push_back(w);
}
else // Weight is 1
adj[v].push_back(w); // Add w to v’s list.
}
// To print the shortest path stored in parent[]
int Graph::printShortestPath(int parent[], int s, int d)
{
static int level = 0;
1693
Chapter 251. Shortest Path in a weighted Graph where weight of an edge is 1 or 2
1694
Chapter 251. Shortest Path in a weighted Graph where weight of an edge is 1 or 2
if (s == dest)
return printShortestPath(parent, s, dest);
queue.pop_front();
// Get all adjacent vertices of the dequeued vertex s
// If a adjacent has not been visited, then mark it
// visited and enqueue it
for (i = adj[s].begin(); i != adj[s].end(); ++i)
{
if (!visited[*i])
{
visited[*i] = true;
queue.push_back(*i);
parent[*i] = s;
}
}
}
}
// Driver program to test methods of graph class
int main()
{
// Create a graph given in the above diagram
int V = 4;
Graph g(V);
g.addEdge(0, 1, 2);
g.addEdge(0, 2, 2);
g.addEdge(1, 2, 1);
g.addEdge(1, 3, 1);
g.addEdge(2, 0, 1);
g.addEdge(2, 3, 2);
g.addEdge(3, 3, 2);
int src = 0, dest = 3;
cout << "\nShortest Distance between " << src
<< " and " << dest << " is "
<< g.findShortestPath(src, dest);
return 0;
}
Python
1695
Chapter 251. Shortest Path in a weighted Graph where weight of an edge is 1 or 2
#This class represents a directed graph using adjacency list representation
class Graph:
def __init__(self,vertices):
self.V = vertices #No. of vertices
self.V_org = vertices
self.graph = defaultdict(list) # default dictionary to store graph
# function to add an edge to graph
def addEdge(self,u,v,w):
if w == 1:
self.graph[u].append(v)
else:
'''split all edges of weight 2 into two
edges of weight 1 each. The intermediate
vertex number is maximum vertex number + 1,
that is V.'''
self.graph[u].append(self.V)
self.graph[self.V].append(v)
self.V = self.V + 1
# To print the shortest path stored in parent[]
def printPath(self, parent, j):
Path_len = 1
if parent[j] == -1 and j < self.V_org : #Base Case : If j is source
print j,
return 0 # when parent[-1] then path length = 0
l = self.printPath(parent , parent[j])
#incerement path length
Path_len = l + Path_len
# print node only if its less than original node length.
# i.e do not print any new node that has been added later
if j < self.V_org :
print j,
return Path_len
''' This function mainly does BFS and prints the
shortest path from src to dest. It is assumed
that weight of every edge is 1'''
def findShortestPath(self,src, dest):
# Mark all the vertices as not visited
# Initialize parent[] and visited[]
visited =[False]*(self.V)
1696
Chapter 251. Shortest Path in a weighted Graph where weight of an edge is 1 or 2
parent =[-1]*(self.V)
# Create a queue for BFS
queue=[]
# Mark the source node as visited and enqueue it
queue.append(src)
visited[src] = True
while queue :
# Dequeue a vertex from queue
s = queue.pop(0)
# if s = dest then print the path and return
if s == dest:
return self.printPath(parent, s)
# Get all adjacent vertices of the dequeued vertex s
# If a adjacent has not been visited, then mark it
# visited and enqueue it
for i in self.graph[s]:
if visited[i] == False:
queue.append(i)
visited[i] = True
parent[i] = s
# Create a graph given in the above diagram
g = Graph(4)
g.addEdge(0, 1, 2)
g.addEdge(0, 2, 2)
g.addEdge(1, 2, 1)
g.addEdge(1, 3, 1)
g.addEdge(2, 0, 1)
g.addEdge(2, 3, 2)
g.addEdge(3, 3, 2)
src = 0; dest = 3
print ("Shortest Path between %d and %d is " %(src, dest)),
l = g.findShortestPath(src, dest)
print ("\nShortest Distance between %d and %d is %d " %(src, dest, l)),
#This code is contributed by Neelam Yadav
Output :
1697
Chapter 251. Shortest Path in a weighted Graph where weight of an edge is 1 or 2
How is this approach O(V+E)? In worst case, all edges are of weight 2 and we need to do
O(E) operations to split all edges and 2V vertices, so the time complexity becomes O(E) +
O(V+E) which is O(V+E).
This article is contributed by Aditya Goel. Please write comments if you find anything
incorrect, or you want to share more information about the topic discussed above
Source
https://www.geeksforgeeks.org/shortest-path-weighted-graph-weight-edge-1-2/
1698
Chapter 252
One solution is to solve in O(VE) time using Bellman–Ford. If there are no negative weight
cycles, then we can solve in O(E + VLogV) time using Dijkstra’s algorithm.
Since the graph is unweighted, we can solve this problem in O(V + E) time. The idea is
to use a modified version of Breadth-first search in which we keep storing the predecessor
of a given vertex while doing the breadth first search. This algorithm will work even when
negative weight cycles are present in the graph.
We first initialize an array dist[0, 1, …., v-1] such that dist[i] stores the distance of vertex
i from the source vertex and array pred[0, 1, ….., v-1] such that pred[i] represents the
immediate predecessor of the vertex i in the breadth first search starting from the source.
1699
Chapter 252. Shortest path in an unweighted graph
Now we get the length of the path from source to any other vertex in O(1) time from array
d, and for printing the path from source to any vertex we can use array p and that will
take O(V) time in worst case as V is the size of array P. So most of the time of algorithm
is spent in doing the Breadth first search from given source which we know takes O(V+E)
time. Thus time complexity of our algorithm is O(V+E).
Take the following unweighted graph as an example:
Following is the complete algorithm for finding the shortest path:
1700
Chapter 252. Shortest path in an unweighted graph
1701
Chapter 252. Shortest path in an unweighted graph
path.push_back(crawl);
while (pred[crawl] != -1) {
path.push_back(pred[crawl]);
crawl = pred[crawl];
}
// distance from source is in distance array
cout << "Shortest path length is : "
<< dist[dest];
// printing path from source to destination
cout << "\nPath is::\n";
for (int i = path.size() - 1; i >= 0; i--)
cout << path[i] << " ";
}
// Driver program to test above functions
int main()
{
// no. of vertices
int v = 8;
// array of vectors is used to store the graph
// in the form of an adjacency list
vector<int> adj[v];
// Creating graph given in the above diagram.
// add_edge function takes adjacency list, source
// and destination vertex as argument and forms
// an edge between them.
add_edge(adj, 0, 1);
add_edge(adj, 0, 3);
add_edge(adj, 1, 2);
add_edge(adj, 3, 4);
add_edge(adj, 3, 7);
add_edge(adj, 4, 5);
add_edge(adj, 4, 6);
add_edge(adj, 4, 7);
add_edge(adj, 5, 6);
add_edge(adj, 6, 7);
int source = 0, dest = 7;
printShortestDistance(adj, source, dest, v);
return 0;
}
Output:
1702
Chapter 252. Shortest path in an unweighted graph
Source
https://www.geeksforgeeks.org/shortest-path-unweighted-graph/
1703
Chapter 253
Shortest path to reach one prime to other by changing single digit at a time - GeeksforGeeks
Given two four digit prime numbers, suppose 1033 and 8179, we need to find the shortest
path from 1033 to 8179 by altering only single digit at a time such that every number that
we get after changing a digit is prime. For example a solution is 1033, 1733, 3733, 3739,
3779, 8779, 8179
Examples:
The question can be solved by BFS and it is a pretty interesting to solve as a starting
problem for beginners. We first find out all 4 digit prime numbers till 9999 using technique
of Sieve of Eratosthenes. And then using those numbers formed the graph using adjacency
list. After forming the adjacency list, we used simple BFS to solve the problem.
1704
Chapter 253. Shortest path to reach one prime to other by changing single digit at a time
#include <bits/stdc++.h>
using namespace std;
class graph {
int V;
list<int>* l;
public:
graph(int V)
{
this->V = V;
l = new list<int>[V];
}
void addedge(int V1, int V2)
{
l[V1].push_back(V2);
l[V2].push_back(V1);
}
int bfs(int in1, int in2);
};
// Finding all 4 digit prime numbers
void SieveOfEratosthenes(vector<int>& v)
{
// Create a boolean array "prime[0..n]" and initialize
// all entries it as true. A value in prime[i] will
// finally be false if i is Not a prime, else true.
int n = 9999;
bool prime[n + 1];
memset(prime, true, sizeof(prime));
for (int p = 2; p * p <= n; p++) {
// If prime[p] is not changed, then it is a prime
if (prime[p] == true) {
// Update all multiples of p
for (int i = p * p; i <= n; i += p)
prime[i] = false;
}
}
// Forming a vector of prime numbers
for (int p = 1000; p <= n; p++)
if (prime[p])
v.push_back(p);
}
1705
Chapter 253. Shortest path to reach one prime to other by changing single digit at a time
1706
Chapter 253. Shortest path to reach one prime to other by changing single digit at a time
{
// Generate all 4 digit
vector<int> pset;
SieveOfEratosthenes(pset);
// Create a graph where node numbers are indexes
// in pset[] and there is an edge between two
// nodes only if they differ by single digit.
graph g(pset.size());
for (int i = 0; i < pset.size(); i++)
for (int j = i + 1; j < pset.size(); j++)
if (compare(pset[i], pset[j]))
g.addedge(i, j);
// Since graph nodes represent indexes of numbers
// in pset[], we find indexes of num1 and num2.
int in1, in2;
for (int j = 0; j < pset.size(); j++)
if (pset[j] == num1)
in1 = j;
for (int j = 0; j < pset.size(); j++)
if (pset[j] == num2)
in2 = j;
return g.bfs(in1, in2);
}
// Driver code
int main()
{
int num1 = 1033, num2 = 8179;
cout << shortestPath(num1, num2);
return 0;
}
Output :
1707
Chapter 253. Shortest path to reach one prime to other by changing single digit at a time
Source
https://www.geeksforgeeks.org/shortest-path-reach-one-prime-changing-single-digit-time/
1708
Chapter 254
1709
Chapter 254. Some interesting shortest path questions Set 1
Question 4: Given a directed acyclic weighted graph, how to find the shortest
path from a source s to a destination t in O(V+E) time?
See: Shortest Path in Directed Acyclic Graph
More Questions See following links for more questions.
http://algs4.cs.princeton.edu/44sp/
https://www.geeksforgeeks.org/algorithms-gq/graph-shortest-paths-gq/
Source
https://www.geeksforgeeks.org/interesting-shortest-path-questions-set-1/
1710
Chapter 255
Stepping Numbers
Input : n = 0, m = 21
Output : 0 1 2 3 4 5 6 7 8 9 10 12 21
Input : n = 10, m = 15
Output : 10, 12
1711
Chapter 255. Stepping Numbers
Java
1712
Chapter 255. Stepping Numbers
1713
Chapter 255. Stepping Numbers
// Display Stepping Numbers in the range [n,m]
displaySteppingNumbers(n,m);
}
}
C#
1714
Chapter 255. Stepping Numbers
Output :
0 1 2 3 4 5 6 7 8 9 10 12 21
1715
Chapter 255. Stepping Numbers
• Every single digit number is considered as a stepping Number, so bfs traversal for
every digit will give all the stepping numbers starting from that digit.
• Do a bfs/dfs traversal for all the numbers from [0,9].
Note: For node 0, no need to explore neighbors during BFS traversal since it will lead to
01, 012, 010 and these will be covered by the BFS traversal starting from node 1.
1716
Chapter 255. Stepping Numbers
1717
Chapter 255. Stepping Numbers
q.push(stepNumB);
}
}
}
// Prints all stepping numbers in range [n, m]
// using BFS.
void displaySteppingNumbers(int n, int m)
{
// For every single digit Number 'i'
// find all the Stepping Numbers
// starting with i
for (int i = 0 ; i <= 9 ; i++)
bfs(n, m, i);
}
//Driver program to test above function
int main()
{
int n = 0, m = 21;
// Display Stepping Numbers in the
// range [n,m]
displaySteppingNumbers(n,m);
return 0;
}
Java
1718
Chapter 255. Stepping Numbers
1719
Chapter 255. Stepping Numbers
{
// For every single digit Number 'i'
// find all the Stepping Numbers
// starting with i
for (int i = 0 ; i <= 9 ; i++)
bfs(n, m, i);
}
//Driver code
public static void main(String args[])
{
int n = 0, m = 21;
// Display Stepping Numbers in
// the range [n,m]
displaySteppingNumbers(n,m);
}
}
1720
Chapter 255. Stepping Numbers
// lastDigit - 1
int stepNumA = stepNum*10 + (lastDigit-1);
int stepNumB = stepNum*10 + (lastDigit+1);
// If lastDigit is 0 then only possible
// digit after 0 can be 1 for a Stepping
// Number
if (lastDigit == 0)
dfs(n, m, stepNumB);
// If lastDigit is 9 then only possible
// digit after 9 can be 8 for a Stepping
// Number
else if(lastDigit == 9)
dfs(n, m, stepNumA);
else
{
dfs(n, m, stepNumA);
dfs(n, m, stepNumB);
}
}
// Method displays all the stepping
// numbers in range [n, m]
void displaySteppingNumbers(int n, int m)
{
// For every single digit Number 'i'
// find all the Stepping Numbers
// starting with i
for (int i = 0 ; i <= 9 ; i++)
dfs(n, m, i);
}
//Driver program to test above function
int main()
{
int n = 0, m = 21;
// Display Stepping Numbers in
// the range [n,m]
displaySteppingNumbers(n,m);
return 0;
}
Java
1721
Chapter 255. Stepping Numbers
import java.util.*;
class Main
{
// Method display's all the stepping numbers
// in range [n, m]
public static void dfs(int n,int m,int stepNum)
{
// If Stepping Number is in the
// range [n,m] then display
if (stepNum <= m && stepNum >= n)
System.out.print(stepNum + " ");
// If Stepping Number is 0 or greater
// than m then return
if (stepNum == 0 || stepNum > m)
return ;
// Get the last digit of the currently
// visited Stepping Number
int lastDigit = stepNum % 10;
// There can be 2 cases either digit
// to be appended is lastDigit + 1 or
// lastDigit - 1
int stepNumA = stepNum*10 + (lastDigit-1);
int stepNumB = stepNum*10 + (lastDigit+1);
// If lastDigit is 0 then only possible
// digit after 0 can be 1 for a Stepping
// Number
if (lastDigit == 0)
dfs(n, m, stepNumB);
// If lastDigit is 9 then only possible
// digit after 9 can be 8 for a Stepping
// Number
else if(lastDigit == 9)
dfs(n, m, stepNumA);
else
{
dfs(n, m, stepNumA);
dfs(n, m, stepNumB);
}
}
// Prints all stepping numbers in range [n, m]
// using DFS.
1722
Chapter 255. Stepping Numbers
Output:
0 1 10 12 2 21 3 4 5 6 7 8 9
Source
https://www.geeksforgeeks.org/stepping-numbers/
1723
Chapter 256
1724
Chapter 256. Subtree of all nodes in a tree using DFS
Examples :
Input: N = 5
0 1
1 2
0 3
3 4
Output:
Subtree of node 0 is 1 2 3 4
Subtree of node 1 is 2
Subtree of node 3 is 4
Input: N = 7
0 1
1 2
2 3
0 4
4 5
4 6
Output:
1725
Chapter 256. Subtree of all nodes in a tree using DFS
Subtree of node 0 is 1 2 3 4 5 6
Subtree of node 1 is 2 3
Subtree of node 4 is 5 6
Approach: Do DFS traversal for every node and print all the nodes which are reachable
from a particular node.
Explanation of below code:
3. Now, recursively call dfs function till all elements traversed of adj[0].
4. Now, dfs(1, 2) is called, Now start[1] = 1, dfs_order.push_back(1), visited[1] = 1 after
adj[1] elements is traversed.
5. Now adj [1] is traversed which contain only node 2 when adj[2] is traversed it contains
no element, it will break and end[1]=2.
6. Similarly, all nodes traversed and store dfs_order in array to find subtree of nodes.
1726
Chapter 256. Subtree of all nodes in a tree using DFS
1727
Chapter 256. Subtree of all nodes in a tree using DFS
dfs(0, c);
// Print child nodes
Print(n);
return 0;
}
Source
https://www.geeksforgeeks.org/sub-tree-nodes-tree-using-dfs/
1728
Chapter 257
Example:
For the graph in diagram,
A depends on C and D i.e. 2
B depends on C i.e. 1
D depends on C i.e. 1
And C depends on none.
Hence answer -> 0 + 1 + 1 + 2 = 4
Asked in : Flipkart Interview
Idea is to check adjacency list and find how many edges are there from each vertex and
1729
Chapter 257. Sum of dependencies in a graph
Java
1730
Chapter 257. Sum of dependencies in a graph
{
// To add an edge
static void addEdge(Vector <Integer> adj[], int u,int v)
{
adj[u].addElement((v));
}
// find the sum of all dependencies
static int findSum(Vector<Integer> adj[], int V)
{
int sum = 0;
// just find the size at each vector's index
for (int u = 0; u < V; u++)
sum += adj[u].size();
return sum;
}
// Driver method
public static void main(String[] args)
{
int V = 4;
Vector<Integer> adj[] = new Vector[V];
for (int i = 0; i < adj.length; i++) {
adj[i] = new Vector<>();
}
addEdge(adj, 0, 2);
addEdge(adj, 0, 3);
addEdge(adj, 1, 3);
addEdge(adj, 2, 3);
System.out.println("Sum of dependencies is " +
findSum(adj, V));
}
}
// This code is contributed by Gaurav Miglani
Output:
Sum of dependencies is 4
1731
Chapter 257. Sum of dependencies in a graph
Source
https://www.geeksforgeeks.org/sum-dependencies-graph/
1732
Chapter 258
Sum of the minimum elements in all connected components of an undirected graph - Geeks-
forGeeks
Given an array A of N numbers where Ai represent the value of the (i+1)th node. Also
given are M pair of edges where u and v represent the nodes that are connected by an edge.
The task is to find the sum of the minimum element in all the connected components of
the given undirected graph. If a node has no connectivity to any other node, count it as a
component with one node.
Examples:
1733
Chapter 258. Sum of the minimum elements in all connected components of an undirected
graph
Approach: Finding connected components for an undirected graph is an easier task. Do-
ing either a BFS or DFS starting from every unvisited vertex will give us our connected
components. Create a visited[] array which has initially all nodes marked as False. Iterate
all the nodes, if the node is not visited, call DFS() function so that all the nodes connected
directly or indirectly to the node are marked as visited. While visiting all the directly or
indirectly connected nodes, store the minimum value of all nodes. Create a variable sum
which stores the summation of the minimum of all these connected components. Once all
the nodes are visited, sum will have the answer to the problem.
Below is the implementation of the above approach:
1734
Chapter 258. Sum of the minimum elements in all connected components of an undirected
graph
// Traversed in all the connected nodes
for (int i : graph[node]) {
if (!visited[i])
dfs(i, a, mini);
}
}
// Function to add the edges
void addedge(int u, int v)
{
graph[u - 1].push_back(v - 1);
graph[v - 1].push_back(u - 1);
}
// Function that returns the sum of all minimums
// of connected componenets of graph
int minimumSumConnectedComponents(int a[], int n)
{
// Initially sum is 0
int sum = 0;
// Traverse for all nodes
for (int i = 0; i < n; i++) {
if (!visited[i]) {
int mini = a[i];
dfs(i, a, mini);
sum += mini;
}
}
// Returns the answer
return sum;
}
// Driver Code
int main()
{
int a[] = {1, 6, 2, 7, 3, 8, 4, 9, 5, 10};
// Add edges
addedge(1, 2);
addedge(3, 4);
addedge(5, 6);
addedge(7, 8);
addedge(9, 10);
int n = sizeof(a) / sizeof(a[0]);
1735
Chapter 258. Sum of the minimum elements in all connected components of an undirected
graph
// Calling Function
cout << minimumSumConnectedComponents(a, n);
return 0;
}
Output:
15
Source
https://www.geeksforgeeks.org/sum-of-the-minimum-elements-in-all-connected-components-of-an-undirected-graph
1736
Chapter 259
1737
Chapter 259. Topological Sort of a graph using departure time of vertex
Please note that the first vertex in topological sorting is always a vertex with in-degree as
0 (a vertex with no incoming edges). For above graph, vertex 4 and 5 have no incoming
edges.
We have already discussed a DFS-based algorithm using stack and Kahn’s Algorithm for
Topological Sorting. We have also discussed how to print all topological sorts of the DAG
here. In this post, another DFS based approach is discussed for finding Topological sort of
a graph by introducing concept of arrival and departure time of a vertex in DFS.
What is Arrival Time & Departure Time of Vertices in DFS?
In DFS, Arrival Time is the time at which the vertex was explored for the first time and
Departure Time is the time at which we have explored all the neighbors of the vertex and
we are ready to backtrack.
How to find Topological Sort of a graph using departure time?
To find Topological Sort of a graph, we run DFS starting from all unvisited vertices one
by one. For any vertex, before exploring any of its neighbors, we note the arrival time of
that vertex and after exploring all the neighbors of the vertex, we note its departure time.
Please note only departure time is needed to find Topological Sort of a graph, so we can skip
arrival time of vertex. Finally, after we have visited all the vertices of the graph, we print
the vertices in order of their decreasing departure time which is our desired Topological
Order of Vertices.
Below is C++ implementation of above idea –
1738
Chapter 259. Topological Sort of a graph using departure time of vertex
Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V];
}
Graph::~Graph()
{
delete[] adj;
}
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w); // Add w to v's list.
}
// The function to do DFS() and stores departure time
// of all vertex
void Graph::DFS(int v, vector<bool> &visited,
vector<int> &departure, int &time)
{
visited[v] = true;
// time++; // arrival time of vertex v
for(int i : adj[v])
if(!visited[i])
DFS(i, visited, departure, time);
// set departure time of vertex v
departure[++time] = v;
}
// The function to do Topological Sort. It uses DFS().
void Graph::topologicalSort()
{
// vector to store departure time of vertex.
vector<int> departure(V, -1);
// Mark all the vertices as not visited
vector<bool> visited(V, false);
int time = -1;
// perform DFS on all unvisited vertices
for(int i = 0; i < V; i++)
if(!visited[i])
DFS(i, visited, departure, time);
1739
Chapter 259. Topological Sort of a graph using departure time of vertex
Output:
Source
https://www.geeksforgeeks.org/topological-sorting-using-departure-time-of-vertex/
1740
Chapter 260
1741
Chapter 260. Total number of Spanning Trees in a Graph
After applying STEP 2 and STEP 3, adjacency matrix will look like
The co-factor for (1, 1) is 8. Hence total no. of spanning tree that can be formed is 8.
NOTE- Co-factor for all the elements will be same. Hence we can compute co-factor for any
element of the matrix.
This method is also known as Kirchhoff’s Theorem. It can be applied to complete graphs
also.
Please refer below link for proof of above procedure.
https://en.wikipedia.org/wiki/Kirchhoff%27s_theorem#Proof_outline
Source
https://www.geeksforgeeks.org/total-number-spanning-trees-graph/
1742
Chapter 261
We have discussed a O(V3 ) solution for this here. The solution was based Floyd Warshall
Algorithm. In this post a O(V2 ) algorithm for the same is discussed.
Below are abstract steps of algorithm.
1. Create a matrix tc[V][V] that would finally have transitive closure of given graph.
Initialize all entries of tc[][] as 0.
2. Call DFS for every node of graph to mark reachable vertices in tc[][]. In recursive calls
to DFS, we don’t call DFS for an adjacent vertex if it is already marked as reachable
in tc[][].
Below is implementation of the above idea. The code uses adjacency list representation of
input graph and builds a matrix tc[V][V] such that tc[u][v] would be true if v is reachable
from u.
C/C++
1743
Chapter 261. Transitive Closure of a Graph using DFS
1744
Chapter 261. Transitive Closure of a Graph using DFS
// recursive DFSUtil()
void Graph::transitiveClosure()
{
// Call the recursive helper function to print DFS
// traversal starting from all vertices one by one
for (int i = 0; i < V; i++)
DFSUtil(i, i); // Every vertex is reachable from self.
for (int i=0; i<V; i++)
{
for (int j=0; j<V; j++)
cout << tc[i][j] << " ";
cout << endl;
}
}
// Driver code
int main()
{
// Create a graph given in the above diagram
Graph g(4);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 2);
g.addEdge(2, 0);
g.addEdge(2, 3);
g.addEdge(3, 3);
cout << "Transitive closure matrix is \n";
g.transitiveClosure();
return 0;
}
Java
1745
Chapter 261. Transitive Closure of a Graph using DFS
// adjacency list
private ArrayList<Integer>[] adjList;
// To store transitive closure
private int[][] tc;
// Constructor
public Graph(int vertices) {
// initialise vertex count
this.vertices = vertices;
this.tc = new int[this.vertices][this.vertices];
// initialise adjacency list
initAdjList();
}
// utility method to initialise adjacency list
@SuppressWarnings("unchecked")
private void initAdjList() {
adjList = new ArrayList[vertices];
for (int i = 0; i < vertices; i++) {
adjList[i] = new ArrayList<>();
}
}
// add edge from u to v
public void addEdge(int u, int v) {
// Add v to u's list.
adjList[u].add(v);
}
// The function to find transitive
// closure. It uses
// recursive DFSUtil()
public void transitiveClosure() {
// Call the recursive helper
// function to print DFS
// traversal starting from all
// vertices one by one
for (int i = 0; i < vertices; i++) {
dfsUtil(i, i);
}
1746
Chapter 261. Transitive Closure of a Graph using DFS
1747
Chapter 261. Transitive Closure of a Graph using DFS
Python
1748
Chapter 261. Transitive Closure of a Graph using DFS
g.addEdge(0, 2)
g.addEdge(1, 2)
g.addEdge(2, 0)
g.addEdge(2, 3)
g.addEdge(3, 3)
print "Transitive closure matrix is"
g.transitiveClosure();
# This code is contributed by Neelam Yadav
Output:
References:
http://www.cs.princeton.edu/courses/archive/spr03/cs226/lectures/digraph.4up.pdf
This article is contributed by Aditya Goel. Please write comments if you find anything
incorrect, or you want to share more information about the topic discussed above
Source
https://www.geeksforgeeks.org/transitive-closure-of-a-graph-using-dfs/
1749
Chapter 262
Transpose graph
Transpose Graph
1750
Chapter 262. Transpose graph
We traverse the adjacency list and as we find a vertex v in the adjacency list of vertex u
which indicates an edge from u to v in main graph, we just add an edge from v to u in
the transpose graph i.e. add u in the adjacency list of vertex v of the new graph. Thus
traversing lists of all vertices of main graph we can get the transpose graph. Thus the total
time complexity of the algorithm is O(V+E) where V is number of vertices of graph and E
is the number of edges of the graph.
Note : It is simple to get the transpose of a graph which is stored in adjacency matrix
format, you just need to get the transpose of that matrix.
1751
Chapter 262. Transpose graph
vector<int> adj[v];
addEdge(adj, 0, 1);
addEdge(adj, 0, 4);
addEdge(adj, 0, 3);
addEdge(adj, 2, 0);
addEdge(adj, 3, 2);
addEdge(adj, 4, 1);
addEdge(adj, 4, 3);
// Finding transpose of graph represented
// by adjacency list adj[]
vector<int> transpose[v];
transposeGraph(adj, transpose, v);
// displaying adjacency list of transpose
// graph i.e. b
displayGraph(transpose, v);
return 0;
}
Output:
0--> 2
1--> 0 4
2--> 3
3--> 0 4
4--> 0
Source
https://www.geeksforgeeks.org/transpose-graph/
1752
Chapter 263
Examples:
1753
Chapter 263. Traveling Salesman Problem (TSP) Implementation
1. Consider city 1 as the starting and ending point. Since route is cyclic, we can consider
any point as starting point.
2. Generate all (n-1)! permutations of cities.
3. Calculate cost of every permutation and keep track of minimum cost permutation.
4. Return the permutation with minimum cost.
1754
Chapter 263. Traveling Salesman Problem (TSP) Implementation
Output:
80
Source
https://www.geeksforgeeks.org/traveling-salesman-problem-tsp-implementation/
1755
Chapter 264
For example, consider the graph shown in figure on right side. A TSP tour in the graph is
1-2-4-3-1. The cost of the tour is 10+25+30+15 which is 80.
The problem is a famous NP hardproblem. There is no polynomial time know solution for
this problem.
Following are different solutions for the traveling salesman problem.
1756
Chapter 264. Travelling Salesman Problem Set 1 (Naive and Dynamic Programming)
Naive Solution:
1) Consider city 1 as the starting and ending point.
2) Generate all (n-1)! Permutationsof cities.
3) Calculate cost of every permutation and keep track of minimum cost permutation.
4) Return the permutation with minimum cost.
Time Complexity: Θ(n!)
Dynamic Programming:
Let the given set of vertices be {1, 2, 3, 4,….n}. Let us consider 1 as starting and ending
point of output. For every other vertex i (other than 1), we find the minimum cost path
with 1 as the starting point, i as the ending point and all vertices appearing exactly once.
Let the cost of this path be cost(i), the cost of corresponding Cycle would be cost(i) + dist(i,
1) where dist(i, 1) is the distance from i to 1. Finally, we return the minimum of all [cost(i)
+ dist(i, 1)] values. This looks simple so far. Now the question is how to get cost(i)?
To calculate cost(i) using Dynamic Programming, we need to have some recursive relation
in terms of sub-problems. Let us define a term C(S, i) be the cost of the minimum cost path
visiting each vertex in set S exactly once, starting at 1 and ending at i.
We start with all subsets of size 2 and calculate C(S, i) for all subsets where S is the subset,
then we calculate C(S, i) for all subsets S of size 3 and so on. Note that 1 must be present
in every subset.
For a set of size n, we consider n-2 subsets each of size n-1 such that all subsets don’t have
nth in them.
Using the above recurrence relation, we can write dynamic programming based solution.
There are at most O(n*2n ) subproblems, and each one takes linear time to solve. The total
running time is therefore O(n2 *2n ). The time complexity is much less than O(n!), but still
exponential. Space required is also exponential. So this approach is also infeasible even for
slightly higher number of vertices.
We will soon be discussing approximate algorithms for travelling salesman problem.
Next Article: Traveling Salesman Problem Set 2
References:
http://www.lsi.upc.edu/~mjserna/docencia/algofib/P07/dynprog.pdf
http://www.cs.berkeley.edu/~vazirani/algorithms/chap6.pdf
Source
https://www.geeksforgeeks.org/travelling-salesman-problem-set-1/
1757
Chapter 265
1758
Chapter 265. Travelling Salesman Problem Set 2 (Approximate using MST)
In this case, the approximate algorithm produces the optimal tour, but it may not produce
optimal tour in all cases.
How is this algorithm 2-approximate? The cost of the output produced by the above
algorithm is never more than twice the cost of best possible output. Let us see how is this
guaranteed by the above algorithm.
Let us define a term full walk to understand this. A full walk is lists all vertices when they
are first visited in preorder, it also list vertices when they are returned after a subtree is
visited in preorder. The full walk of above tree would be 1-2-1-4-1-3-1.
Following are some important facts that prove the 2-approximateness.
1) The cost of best possible Travelling Salesman tour is never less than the cost of MST.
(The definition of MSTsays, it is a minimum cost tree that connects all vertices).
2) The total cost of full walk is at most twice the cost of MST (Every edge of MST is visited
at-most twice)
3) The output of the above algorithm is less than the cost of full walk. In above algorithm,
we print preorder walk as output. In preorder walk, two or more edges of full walk are
replaced with a single edge. For example, 2-1 and 1-4 are replaced by 1 edge 2-4. So if the
graph follows triangle inequality, then this is always true.
From the above three statements, we can conclude that the cost of output produced by the
approximate algorithm is never more than twice the cost of best possible solution.
We have discussed a very simple 2-approximate algorithm for the travelling salesman
problem. There are other better approximate algorithms for the problem. For example
Christofides algorithm is 1.5 approximate algorithm. We will soon be discussing these
algorithms as separate posts.
References:
Introduction to Algorithms 3rd Edition by Clifford Stein, Thomas H. Cormen, Charles E.
Leiserson, Ronald L. Rivest
http://www.personal.kent.edu/~rmuhamma/Algorithms/MyAlgorithms/AproxAlgor/TSP/tsp.htm
Improved By : PranamLashkari
1759
Chapter 265. Travelling Salesman Problem Set 2 (Approximate using MST)
Source
https://www.geeksforgeeks.org/travelling-salesman-problem-set-2-approximate-using-mst/
1760
Chapter 266
Two Clique Problem (Check if Graph can be divided in two Cliques) - GeeksforGeeks
A Clique is a subgraph of graph such that all vertcies in subgraph are completely connected
with each other. Given a Graph, find if it can be divided into two Cliques.
This problem looks tricky at first, but has a simple and interesting solution. A graph can
be divided in two cliques if its complement graph is Bipartitie. So below are two steps to
find if graph can be divided in two Cliques or not.
1761
Chapter 266. Two Clique Problem (Check if Graph can be divided in two Cliques)
2. Return true if complement is Bipartite, else false. Above shown graph is Bipartite.
Checking whether a Graph is Biparitite or no is discussed here.
1762
Chapter 266. Two Clique Problem (Check if Graph can be divided in two Cliques)
1763
Chapter 266. Two Clique Problem (Check if Graph can be divided in two Cliques)
Output :
Yes
Reference:
http://math.stackexchange.com/questions/310092/the-two-clique-problem-is-in-p-or-np-p-np-for-hypothesis
1764
Chapter 266. Two Clique Problem (Check if Graph can be divided in two Cliques)
Source
https://www.geeksforgeeks.org/two-clique-problem-check-graph-can-divided-two-cliques/
1765
Chapter 267
Undirected graph splitting and its application for number pairs - GeeksforGeeks
Graphs can be used for seemingly unconnected problems. Say the problem of cards which
have numbers on both side and you try to create a continuous sequence of numbers using
one side. This problem leads to problems in how to split a graph into connected subsets
with cycles and connected subsets without cycles.
There are known algorithms to detect if the graph contains a circle. Here we modify it to
find all nodes not-connected to circles. We add a Boolean array cyclic initiated as all false,
meaning that no node is known to be connected to a circle.
Then we loop through nodes applied a usual algorithm to determine a circle skipping on
nodes that are already known to be connected to a circle. Whenever we find a new node
connected to a circle we propagate the property to all connected nodes skipping already
designated as connected again.
Main function is a modification of DFS algorithm from article “Detect cycles in undirected
graph“:
All nodes connected to a cycle are designated as such in a linear time.
The algorithm was applied to the following problem from the recent challenge “Germanium”,
which was solved by about 3.5% of participants.
Suppose we have N cards (100000 >= N >= 1) and on both sides of the cards there is a
number ( N are useless and can be discarded. In the same spirit, every car (n, m): n N
allows us to put n upwards and ensured its presence in the sequence, while m is useless
anyway.
If we have a card (n.n): n < N, it ensures that n can always be added to a continuous
sequence that arrived to n-1.
If we have two identical cards (n, m) both n, m can be always added to a sequence if needed,
just to put it on the opposite side.
Now we encode cards into a graph in the following way. The graph nodes are supposed to
be numbered from 0 to N-1. Every node has a set of edges leading to is represented as a
vector, initiated as an empty and overall set of edges is a vector of vectors of integers – edges
1766
Chapter 267. Undirected graph splitting and its application for number pairs
(N).
(n, m) : n, m N – discarded.
(n, m): n N – add to the graph edge (n-1, n-1)
Now it is easy to understand that every cycle in the graph can be used for all nodes od the
graph. A sample: (1, 2) (2, 5), (5, 1) – every number appears on two cards, just pass along
the cycle and put any number once up and another time down:
(1, 2) – 1 up, 2 down
(2, 5) – 2 up, 5 down
(5, 1) – 5 up, 1 down
If any number already put on the upper side, every subsequent card that has the number
must be out this number down, so another number can be shown on the upper side. In the
graph, it means that any number connected by an edge to a number of cycles is free to be
shown. The same is true for a card connected to the card connected to the cycle. So, any
number/node that connected somehow to any cycle cannot provide any problem. Pairs of
identical cards like (1, 2), (1, 2) also produce a small circle in the graph, the same is true
for double cards, like 3, 3 it is a cycle of a node connected to itself.
All parts of the graph that are not connected to any cycle can be split in not connected
smaller graphs. It is more or less obvious that any such fragment has a problematic number
– the biggest in the fragment. We use a similar but much easier algorithm to find such
fragments and all maximums in fragments. The least of it is Q – the smallest number that
cannot be the end of the continuous coverage from the least numbers, the Q above.
In addition to the cyclic array, we add another array: visitedNonCyclic, meaning that this
number already met while passing through a non-cycle fragment.
The maximum in the non-cycle fragment is extracted by recurrent calls to a function:
Please refer findMax() in below code. The graph creation is done in solution() of below
code.
After the graph is created the solution just calls to isCyclic and then to:
The solution, which was inspired by the rather hard recent “Germanium 2018 Codility
Challenge” and brought the gold medal.
Main Idea:
1. Numbers are big, but we demand a continuous sequence from 1 to the last number,
but there are no more than 100 000 numbers. So, the biggest possible is really 100 000, take
it as the first hypothesis
2. Due to the same considerations, the biggest number cannot be bigger than N (amount of
numbers)
3. We can also pass overall numbers and take the biggest which is NN. The result cannot
be bigger than N or NN
4. Taking this into account we can replace all cards like (x, 200 000) into (x, x). Both allow
setting x upwards, x is not a problem thus.
5. Cards with both numbers bigger that N or NN just ignored or disposed
6. If there are cards with the same number on both sides it means that the number is always
OK, cannot be the smallest problematic, so never the answer.
1767
Chapter 267. Undirected graph splitting and its application for number pairs
7. If there are two identical cards like (x, y) and (y, x) it means that both x and y are not
problematic and cannot be the answer
8. Now we introduce the main BIG idea that we translate the set of cards into a graph.
Vortices of the graph are numbered from 0 to M-1, where M is the last possible number
(least of N, NN). Every node has some adjacent nodes, so the set of all edges is a vector of
vectors of integers
8. Every card like (x, y) with both numbers less or equal to M into edge x-1, y-1, so the
first node gets an additional adjacent node and vice versa
9. Some vortices will be connected to themselves due to cards like (3, 3). It is a loop case
of size 1.
10. Some vortices will be connected by two edges or more if there are identical cards. It is
a loop of size 2.
11. Loops of sizes 1 and 2 have numbers that cannot be of any problem. But now we realize
that the same is the case of a cycle of any length. For example, cards are 2, 3; 3, 4; 4, 10; 10,
2; All their numbers have no problem, just put 2, 3, 4, 10 to the upper side. The downside
will have 3, 4, 10, 2.
12. Now if we have a card x, y and we know that x is guaranteed already in another place,
we can put this card x down, y up and ensure that the y is in the resulting sequence.
12. So, if any card is connected to a cycle by an edge, it cannot present a problem since the
cycle is all OK, so this number is also OK.
13. Thus if there is an interconnected subset of nodes of a graph which contains a cycle, all
vortices cannot present any problem.
So, we can apply one of the known algorithms to find loops like in the article “Detect cycle
in an undirected graph” with an addition of propagation
14. We can also designate all nodes in the graph that are connected to a cycle, cycled[].
And we can propagate the property
Just start with some in a cycle, set it as a cycled, then pass over it’s adjacent skipping the
cycled and calling the same function on the adjacent.
15. Using a combination of the known algorithm to detect cycles in an undirected graph
with skipping on cycled already and propagating the property “connected to a cycle”, we
find all nodes connected to cycles. All such nodes are safe, they cannot be a problem
16. But remain nodes not connected to any cycle, their problem can be simplified but
cutting into separated graphs which have no common edges or nodes.
17. But what to do with them? It can be a linear branch or branches that cross one another.
All nodes are different.
18. With some last effort, one can understand that any such set has only one problematic
number – maximum of the set. It can be proven, paying attention that crosses only makes
thing better, but the maximum stays still.
19. So we cut all non-cycled into connected separated entities and find the maximum in
every one.
20. Then we find the minimum of them and this is the final answer!
Examples:
1768
Chapter 267. Undirected graph splitting and its application for number pairs
Output: 4.
Because you can show 3 or 4 by the first card but not both 3 and 4. So, put 3,
while 1 and 2 are by the following cards.
Input : A = [2, 3], B = [2, 3]
Output : 1. Because 1 is missing at all.
Complexity:
#include <algorithm>
#include <vector>
using namespace std;
class Graph {
private:
int V; // No. of vertices
vector<vector<int> > edges; // edges grouped by nodes
bool isCyclicUtil(int v, vector<bool>& visited, int parent);
vector<bool> cyclic;
vector<int> maxInNonCyclicFragments;
int findMax(int v);
vector<bool> visitedNonCyclic;
void setPropagateCycle(int v);
public:
Graph(int V); // Constructor
void addEdge(int v, int w); // to add an edge to graph
// returns true if there is a cycle and
// also designates all connected to a cycle
bool isCyclic();
int getSize() const { return V; }
int GetAnswer();
};
Graph::Graph(int V)
{
this->V = V;
edges = vector<vector<int> >(V, vector<int>());
visitedNonCyclic = cyclic = vector<bool>(V, false);
}
1769
Chapter 267. Undirected graph splitting and its application for number pairs
1770
Chapter 267. Undirected graph splitting and its application for number pairs
return false;
}
bool Graph::isCyclic()
{
// Mark all the vortices as not visited
// and not part of recursion stack
vector<bool> visited(V, false);
// Call the recursive helper function
// to detect cycle in different DFS trees
bool res = false;
for (int u = 0; u < V; u++)
// Don't recur for u if it is already visited{
if (!visited[u] && !cyclic[u]) {
if (isCyclicUtil(u, visited, -1)) {
res = true;
// there was retur true originally
visited = vector<bool>(V, false);
}
}
return res;
}
int Graph::findMax(int v)
{
if (cyclic[v])
return -1;
if (visitedNonCyclic.at(v))
return -1;
int res = v;
visitedNonCyclic.at(v) = true;
for (auto& u2 : edges.at(v)) {
res = max(res, findMax(u2));
}
return res;
}
int Graph::GetAnswer()
{
// cannot be less than, after extract must add 1
int res = V;
for (int u = 0; u < V; u++) {
maxInNonCyclicFragments.push_back(findMax(u));
}
1771
Chapter 267. Undirected graph splitting and its application for number pairs
1772
Chapter 267. Undirected graph splitting and its application for number pairs
1773
Chapter 267. Undirected graph splitting and its application for number pairs
int A2[] = { 4, 2, 1, 6, 5 };
int B2[] = { 3, 2, 1, 7, 7 };
VA = vector<int>(A2, A2 + 5);
VB = vector<int>(B2, B2 + 5);
test(VA, VB, 4);
int A3[] = { 2, 3 };
int B3[] = { 2, 3 };
VA = vector<int>(A3, A3 + 2);
VB = vector<int>(B3, B3 + 2);
test(VA, VB, 1);
return 0;
}
Output:
1
2
Expected: 2 Result: 2
Result: 3
Result: 5
Result: 4
Result: 1
Source
https://www.geeksforgeeks.org/undirected-graph-splitting-and-its-application-for-number-pairs/
1774
Chapter 268
Union-Find Algorithm (Union By Rank and Find by Optimized Path Compression) - Geeks-
forGeeks
Check whether a given graph contains a cycle or not.
Example 1:
Input:
Example 2:
Input:
Prerequisites: Disjoint Set (Or Union-Find), Union By Rank and Path Compression
We have already discussed union-find to detect cycle. Here we discuss find by path compres-
sion, where it is slightly modified to work faster than the original method as we are skipping
one level each time we are going up the graph. Implementation of find function is iterative,
so there is no overhead involved.Time complexity of optimized find function is O(log*(n)),
i.e iterated logarithm, which converges to O(1) for repeated calls.
Refer this link for
Proof of log*(n) complexity of Union-Find
Explanation of find function:
Take Example 1 to understand find function:
1775
Chapter 268. Union-Find Algorithm (Union By Rank and Find by Optimized Path
Compression)
(1)call find(8) for first time and mappings will be done like this:
It took 3 mappings for find function to get the root of node 8. Mappings are illustrated
below:
From node 8, skipped node 7, Reached node 6.
From node 6, skipped node 5, Reached node 4.
From node 4, skipped node 2, Reached node 0.
(2)call find(8) for second time and mappings will be done like this:
It took 2 mappings for find function to get the root of node 8. Mappings are illustrated
below:
From node 8, skipped node 5, node 6 and node 7, Reached node 4.
From node 4, skipped node 2, Reached node 0.
(3)call find(8) for third time and mappings will be done like this:
1776
Chapter 268. Union-Find Algorithm (Union By Rank and Find by Optimized Path
Compression)
Finally, we see it took only 1 mapping for find function to get the root of node 8. Mappings
are illustrated below:
From node 8, skipped node 5, node 6, node 7, node 4, and node 2, Reached node 0.
That is how it converges path from certain mappings to single mapping.
Explanation of example 1:
Initially array size and Arr look like:
Arr[9] = {0, 1, 2, 3, 4, 5, 6, 7, 8}
size[9] = {1, 1, 1, 1, 1, 1, 1, 1, 1}
Consider the edges in the graph, and add them one by one to the disjoint-union set as
follows:
Edge 1: 0-1
find(0)=>0, find(1)=>1, both have different root parent
Put these in single connected component as currently they doesn’t belong to different con-
nected components.
Arr[1]=0, size[0]=2;
Edge 2: 0-2
find(0)=>0, find(2)=>2, both have different root parent
Arr[2]=0, size[0]=3;
Edge 3: 1-3
find(1)=>0, find(3)=>3, both have different root parent
Arr[3]=0, size[0]=3;
Edge 4: 3-4
find(3)=>1, find(4)=>4, both have different root parent
Arr[4]=0, size[0]=4;
Edge 5: 2-4
find(2)=>0, find(4)=>0, both have same root parent
Hence, There is a cycle in graph.
We stop further checking for cycle in graph.
1777
Chapter 268. Union-Find Algorithm (Union By Rank and Find by Optimized Path
Compression)
1778
Chapter 268. Union-Find Algorithm (Union By Rank and Find by Optimized Path
Compression)
Output:
1779
Chapter 268. Union-Find Algorithm (Union By Rank and Find by Optimized Path
Compression)
Source
https://www.geeksforgeeks.org/union-find-algorithm-union-rank-find-optimized-path-compression/
1780
Chapter 269
The above union() and find() are naive and the worst case time complexity is linear. The
trees created to represent subsets can be skewed and can become like a linked list. Following
is an example worst case scenario.
1781
Chapter 269. Union-Find Algorithm Set 2 (Union By Rank and Path Compression)
Do Union(0, 1)
1 2 3
/
0
Do Union(1, 2)
2 3
/
1
/
0
Do Union(2, 3)
3
/
2
/
1
/
0
The above operations can be optimized to O(Log n) in worst case. The idea is to always
attach smaller depth tree under the root of the deeper tree. This technique is called union
by rank. The term rank is preferred instead of height because if path compression technique
(we have discussed it below) is used, then rank is not always equal to height. Also, size (in
place of height) of trees can also be used as rank. Using size as rank also yields worst case
time complexity as O(Logn) (See thisfor proof)
Do Union(0, 1)
1 2 3
/
0
Do Union(1, 2)
1 3
/ \
0 2
1782
Chapter 269. Union-Find Algorithm Set 2 (Union By Rank and Path Compression)
Do Union(2, 3)
1
/ | \
0 2 3
The second optimization to naive method is Path Compression. The idea is to flatten the
tree when find() is called. When find() is called for an element x, root of the tree is returned.
The find() operation traverses up from x to find root. The idea of path compression is to
make the found root as parent of x so that we don’t have to traverse all intermediate nodes
again. If x is root of a subtree, then path (to root) from all nodes under x also compresses.
9
/ / \ \
4 5 6 3
/ / \ / \
0 7 8 1 2
The two techniques complement each other. The time complexity of each operation becomes
even smaller than O(Logn). In fact, amortized time complexity effectively becomes small
constant.
Following is union by rank and path compression based implementation to find a cycle in a
graph.
C++
// A union by rank and path compression based program to detect cycle in a graph
#include <stdio.h>
#include <stdlib.h>
// a structure to represent an edge in the graph
struct Edge
{
int src, dest;
1783
Chapter 269. Union-Find Algorithm Set 2 (Union By Rank and Path Compression)
};
// a structure to represent a graph
struct Graph
{
// V-> Number of vertices, E-> Number of edges
int V, E;
// graph is represented as an array of edges
struct Edge* edge;
};
struct subset
{
int parent;
int rank;
};
// Creates a graph with V vertices and E edges
struct Graph* createGraph(int V, int E)
{
struct Graph* graph = (struct Graph*) malloc( sizeof(struct Graph) );
graph->V = V;
graph->E = E;
graph->edge = (struct Edge*) malloc( graph->E * sizeof( struct Edge ) );
return graph;
}
// A utility function to find set of an element i
// (uses path compression technique)
int find(struct subset subsets[], int i)
{
// find root and make root as parent of i (path compression)
if (subsets[i].parent != i)
subsets[i].parent = find(subsets, subsets[i].parent);
return subsets[i].parent;
}
// A function that does union of two sets of x and y
// (uses union by rank)
void Union(struct subset subsets[], int x, int y)
{
int xroot = find(subsets, x);
int yroot = find(subsets, y);
1784
Chapter 269. Union-Find Algorithm Set 2 (Union By Rank and Path Compression)
// Attach smaller rank tree under root of high rank tree
// (Union by Rank)
if (subsets[xroot].rank < subsets[yroot].rank)
subsets[xroot].parent = yroot;
else if (subsets[xroot].rank > subsets[yroot].rank)
subsets[yroot].parent = xroot;
// If ranks are same, then make one as root and increment
// its rank by one
else
{
subsets[yroot].parent = xroot;
subsets[xroot].rank++;
}
}
// The main function to check whether a given graph contains cycle or not
int isCycle( struct Graph* graph )
{
int V = graph->V;
int E = graph->E;
// Allocate memory for creating V sets
struct subset *subsets =
(struct subset*) malloc( V * sizeof(struct subset) );
for (int v = 0; v < V; ++v)
{
subsets[v].parent = v;
subsets[v].rank = 0;
}
// Iterate through all edges of graph, find sets of both
// vertices of every edge, if sets are same, then there is
// cycle in graph.
for(int e = 0; e < E; ++e)
{
int x = find(subsets, graph->edge[e].src);
int y = find(subsets, graph->edge[e].dest);
if (x == y)
return 1;
Union(subsets, x, y);
}
return 0;
}
1785
Chapter 269. Union-Find Algorithm Set 2 (Union By Rank and Path Compression)
Java
1786
Chapter 269. Union-Find Algorithm Set 2 (Union By Rank and Path Compression)
1787
Chapter 269. Union-Find Algorithm Set 2 (Union By Rank and Path Compression)
1788
Chapter 269. Union-Find Algorithm Set 2 (Union By Rank and Path Compression)
graph.edge[2].src = 0;
graph.edge[2].dest = 2;
if (graph.isCycle(graph) == 1)
System.out.println("Graph contains cycle");
else
System.out.println("Graph doesn't contain cycle");
}
}
// This code is contributed
// by ashwani khemani
Output:
Related Articles :
Union-Find Algorithm Set 1 (Detect Cycle in a an Undirected Graph)
Disjoint Set Data Structures (Java Implementation)
Greedy Algorithms Set 2 (Kruskal’s Minimum Spanning Tree Algorithm)
Job Sequencing Problem Set 2 (Using Disjoint Set)
References:
http://en.wikipedia.org/wiki/Disjoint-set_data_structure
IITD Video Lecture
Improved By : DeepeshThakur, ashwani khemani
Source
https://www.geeksforgeeks.org/union-find-algorithm-set-2-union-by-rank/
1789
Chapter 270
Input : 4 2
1 2 60
3 4 50
Output :2
1 2 60
3 4 50
Explanation:
Connected components are:
1->2 and 3->4
Therefore, our answer is 2 followed by
1 2 60 and 3 4 50.
Input :9 6
7 4 98
5 9 72
4 6 10
1790
Chapter 270. Water Connection Problem
2 8 22
9 7 17
3 1 66
Output :3
2 8 22
3 1 66
5 6 10
Explanation:
Connected components are 3->1,
5->9->7->4->6 and 2->8.
Therefore, our answer is 3 followed by
2 8 22, 3 1 66, 5 6 10
Approach:
Perform DFS from appropriate houses to find all different connected components. The
number of different connected components is our answer t.
The next t lines of the output are the beginning of the connected component, end of the
connected component and the minimum diameter from the start to the end of the connected
component in each line.
Since, tanks can be installed only on the houses having outgoing pipe and no incoming
pipe, therefore these are appropriate houses to start DFS from i.e. perform DFS from such
unvisited houses.
Below is the implementation of above approach:
C++
1791
Chapter 270. Water Connection Problem
1792
Chapter 270. Water Connection Problem
a.push_back(j);
b.push_back(w);
c.push_back(ans);
}
cout << a.size() << endl;
for (int j = 0; j < a.size(); ++j)
cout << a[j] << " " << b[j]
<< " " << c[j] << endl;
}
// driver function
int main()
{
n = 9, p = 6;
memset(rd, 0, sizeof(rd));
memset(cd, 0, sizeof(cd));
memset(wt, 0, sizeof(wt));
int arr[][3] = { { 7, 4, 98 },
{ 5, 9, 72 },
{ 4, 6, 10 },
{ 2, 8, 22 },
{ 9, 7, 17 },
{ 3, 1, 66 } };
solve(arr);
return 0;
}
Java
1793
Chapter 270. Water Connection Problem
1794
Chapter 270. Water Connection Problem
a=new ArrayList<Integer>();
b=new ArrayList<Integer>();
c=new ArrayList<Integer>();
for (int j = 1; j <= n; ++j)
/*If a pipe has no ending vertex
but has starting vertex i.e is
an outgoing pipe then we need
to start DFS with this vertex.*/
if (rd[j] == 0 && cd[j]>0) {
ans = 1000000000;
int w = dfs(j);
// We put the details of
// component in final output
// array
a.add(j);
b.add(w);
c.add(ans);
}
System.out.println(a.size());
for (int j = 0; j < a.size(); ++j)
System.out.println(a.get(j) + " "
+ b.get(j) + " " + c.get(j));
}
// main function
public static void main(String args[])
{
n = 9;
p = 6;
// set the value of the araray
// to zero
for(int i = 0; i < 1100; i++)
rd[i] = cd[i] = wt[i] = 0;
int arr[][] = { { 7, 4, 98 },
{ 5, 9, 72 },
{ 4, 6, 10 },
{ 2, 8, 22 },
{ 9, 7, 17 },
{ 3, 1, 66 } };
solve(arr);
}
1795
Chapter 270. Water Connection Problem
}
// This code is contributed by Arnab Kundu
Output:
3
2 8 22
3 1 66
5 6 10
Source
https://www.geeksforgeeks.org/water-connection-problem/
1796
Chapter 271
Examples:
Input : 4 3 2
Output : {(0, 0), (0, 3), (4, 0), (4, 3),
(3, 0), (1, 3), (3, 3), (4, 2),
(0, 2)}
1797
Chapter 271. Water Jug problem using BFS
#include <bits/stdc++.h>
#define pii pair<int, int>
#define mp make_pair
using namespace std;
void BFS(int a, int b, int target)
{
// Map is used to store the states, every
// state is hashed to binary value to
// indicate either that state is visited
// before or not
map<pii, int> m;
bool isSolvable = false;
vector<pii> path;
queue<pii> q; // queue to maintain states
q.push({ 0, 0 }); // Initialing with initial state
while (!q.empty()) {
pii u = q.front(); // current state
q.pop(); // pop off used state
// if this state is already visited
if (m[{ u.first, u.second }] == 1)
continue;
// doesn't met jug constraints
if ((u.first > a || u.second > b ||
u.first < 0 || u.second < 0))
continue;
// filling the vector for constructing
// the solution path
path.push_back({ u.first, u.second });
// marking current state as visited
m[{ u.first, u.second }] = 1;
// if we reach solution state, put ans=1
if (u.first == target || u.second == target) {
isSolvable = true;
if (u.first == target) {
if (u.second != 0)
// fill final state
path.push_back({ u.first, 0 });
1798
Chapter 271. Water Jug problem using BFS
}
else {
if (u.first != 0)
// fill final state
path.push_back({ 0, u.second });
}
// print the solution path
int sz = path.size();
for (int i = 0; i < sz; i++)
cout << "(" << path[i].first
<< ", " << path[i].second << ")\n";
break;
}
// if we have not reached final state
// then, start developing intermediate
// states to reach solution state
q.push({ u.first, b }); // fill Jug2
q.push({ a, u.second }); // fill Jug1
for (int ap = 0; ap <= max(a, b); ap++) {
// pour amount ap from Jug2 to Jug1
int c = u.first + ap;
int d = u.second - ap;
// check if this state is possible or not
if (c == a || (d == 0 && d >= 0))
q.push({ c, d });
// Pour amount ap from Jug 1 to Jug2
c = u.first - ap;
d = u.second + ap;
// check if this state is possible or not
if ((c == 0 && c >= 0) || d == b)
q.push({ c, d });
}
q.push({ a, 0 }); // Empty Jug2
q.push({ 0, b }); // Empty Jug1
}
// No, solution exists if ans=0
if (!isSolvable)
cout << "No solution";
1799
Chapter 271. Water Jug problem using BFS
}
// Driver code
int main()
{
int Jug1 = 4, Jug2 = 3, target = 2;
cout << "Path from initial state "
"to solution state :\n";
BFS(Jug1, Jug2, target);
return 0;
}
Output:
Source
https://www.geeksforgeeks.org/water-jug-problem-using-bfs/
1800
Chapter 272
The idea is to use BFS. We start from the given start word, traverse all words that adjacent
(differ by one character) to it and keep doing so until we find the target word or we have
traversed all words.
Below is C++ implementation of above idea.
C
1801
Chapter 272. Word Ladder (Length of shortest chain to reach a target word)
// To check if strings differ by exactly one character
bool isadjacent(string& a, string& b)
{
int count = 0; // to store count of differences
int n = a.length();
// Iterate through all characters and return false
// if there are more than one mismatching characters
for (int i = 0; i < n; i++)
{
if (a[i] != b[i]) count++;
if (count > 1) return false;
}
return count == 1 ? true : false;
}
// A queue item to store word and minimum chain length
// to reach the word.
struct QItem
{
string word;
int len;
};
// Returns length of shortest chain to reach 'target' from 'start'
// using minimum number of adjacent moves. D is dictionary
int shortestChainLen(string& start, string& target, set<string> &D)
{
// Create a queue for BFS and insert 'start' as source vertex
queue<QItem> Q;
QItem item = {start, 1}; // Chain length for start word is 1
Q.push(item);
// While queue is not empty
while (!Q.empty())
{
// Take the front word
QItem curr = Q.front();
Q.pop();
// Go through all words of dictionary
for (set<string>::iterator it = D.begin(); it != D.end(); it++)
{
// Process a dictionary word if it is adjacent to current
// word (or vertex) of BFS
string temp = *it;
if (isadjacent(curr.word, temp))
1802
Chapter 272. Word Ladder (Length of shortest chain to reach a target word)
{
// Add the dictionary word to Q
item.word = temp;
item.len = curr.len + 1;
Q.push(item);
// Remove from dictionary so that this word is not
// processed again. This is like marking visited
D.erase(temp);
// If we reached target
if (temp == target)
return item.len;
}
}
}
return 0;
}
// Driver program
int main()
{
// make dictionary
set<string> D;
D.insert("poon");
D.insert("plee");
D.insert("same");
D.insert("poie");
D.insert("plie");
D.insert("poin");
D.insert("plea");
string start = "toon";
string target = "plea";
cout << "Length of shortest chain is: "
<< shortestChainLen(start, target, D);
return 0;
}
Python
1803
Chapter 272. Word Ladder (Length of shortest chain to reach a target word)
1804
Chapter 272. Word Ladder (Length of shortest chain to reach a target word)
D.remove(temp)
# If we reached target
if temp == target:
return item.len
D = []
D.append("poon")
D.append("plee")
D.append("same")
D.append("poie")
D.append("plie")
D.append("poin")
D.append("plea")
start = "toon"
target = "plea"
print "Length of shortest chain is: %d" \
% shortestChainLen(start, target, D)
# This code is contributed by Divyanshu Mehta
Output:
Time Complexity of the above code is O(n²m) where n is the number of entries originally
in the dictionary and m is the size of the string
Thanks to Gaurav Ahirwar and Rajnish Kumar Jha for above solution.
Source
https://www.geeksforgeeks.org/word-ladder-length-of-shortest-chain-to-reach-a-target-word/
1805