0% found this document useful (0 votes)
30 views146 pages

Unit III

The document provides an overview of graphs as non-linear data structures, detailing their components such as vertices and edges, and various types of graphs including directed, undirected, weighted, and unweighted graphs. It also discusses graph terminologies, operations in graph abstract data types (ADT), and different storage representations like adjacency matrices and lists, along with C++ implementations for both. Additionally, it covers graph traversal techniques, specifically depth-first search (DFS) and breadth-first search (BFS).

Uploaded by

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

Unit III

The document provides an overview of graphs as non-linear data structures, detailing their components such as vertices and edges, and various types of graphs including directed, undirected, weighted, and unweighted graphs. It also discusses graph terminologies, operations in graph abstract data types (ADT), and different storage representations like adjacency matrices and lists, along with C++ implementations for both. Additionally, it covers graph traversal techniques, specifically depth-first search (DFS) and breadth-first search (BFS).

Uploaded by

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

UNIT III

GRAPH
Graphs - Basic Concepts

• Non-linear data structures are used to represent the data containing a network or

hierarchical relationship among the elements.

• Graphs are one of the most important non linear data structures.

• Graphs as non-linear data structures represent the relationship among data elements,

having more than one predecessor and/or successor.

• A graph G is a collection of nodes (vertices) and arcs joining a pair of the nodes

(edges). Edges between two vertices represent the relationship between them.

• For finite graphs,V and E are finite. We can denote the graph as G = (V, E).
• Graph in Data Structure is a non-linear data structure that consists of nodes and edges

which connects them.

• A Graph in Data Structure is a collection of nodes that consists of data and are

connected to other nodes of the graph.


Graph Terminologies in Data Structure

Term Description

Vertex Every individual data element is called a vertex or a node.


Edge Arc It is a connecting link between two nodes or vertices. Each edge has two ends and is
represented as (starting Vertex, and ending Vertex).
Undirected Edge edges that do not have a direction.
Directed Edge It is a unidirectional edge. A directed edge is an edge contained in a direction.
Weighted Edge An edge with value (cost) on it.
Degree The total number of edges connected to a vertex in a graph.
In degree The total number of incoming edges connected to a vertex.
Out degree The total number of outgoing edges connected to a vertex.
Self-loop An edge is called a self-loop if its two endpoints coincide.
Adjacency Vertices are said to be adjacent if an edge is connected.
Path A sequence of nodes connected through edges in a graph data structure is known as a path.
Cycles A cycle is a path in the graph data structure, that ends at the node right from where it starts.
Adjacent Nodes Vertices that are both endpoints of the same edge.
Adjacent Edges Adjacent edges are two distinct edges that share an end vertex.
Edge Cost The value that an edge holds to travel to another vertex. It is also known as Edge Weight.
Types of Graphs in Data Structure

Simple Graph - A graph having no more than a single


edge between all the adjacent nodes of the graph data
structure.

Multigraph -
A graph having multiple edges to join the same vertices
or nodes.

Undirected Graph -

A graph where the adjacent nodes are not directed

towards each other.


Directed Graph - A graph where the adjacent nodes
are directed towards each other. Also known as
Digraph.

Weighted Graph - A graph where the edges or


connections between its nodes have an edge cost or
weight.

Unweighted Graph - A graph where the edges or


connections between its nodes do not have an edge
cost or weight.
Connected Graph - A graph in which all the nodes are
connected to each other with edges with a single
component.

Disconnected Graph - A graph in which all the nodes


are not connected to each other with edges making
multiple components present in the graph data structure.

Cyclic Graph - A graph that constitutes any cycle where


we reach an already visited vertex.
Graph ADT:-
ADT Graph
{
Instances : a nonempty set of vertices and a set of edges, where each edge is in between a pair of
vertices.
Operations:
Create(); //return an empty graph
InsertVertex(V); // insert V in to the graph
InsertEdge(u,v); // insert new edge between u and v
DeleteVertex(V); // delete V from the graph
DeleteEdge(u,v); // delete an edge from graph between u and v
Bool IsEmpty(graph); //return TRUE else return FALSE
Adjacent(V); // return a list of all vertices that are adjacent to V
int degree(V);
}
Storage representation
• There are two standard representations of a graph given as follows:
1. Adjacency matrix (sequential representation)
2. Adjacency list (linked representation)
• Adjacency Matrix -
• An Adjacency Matrix is the simplest way to represent a graph.
• It is a 2D array of V x V vertices, with each row and column representing a
vertex.
• The matrix consists of “0” or “1”.
• 0 depicts that there is no path, while 1 represents that there is a path.
• For a graph G = (V, E), suppose V = {1, 2, …, n}. The adjacency matrix for G is a
two dimensional n X n Boolean matrix A and can be represented as
Adjacency Matrix representation
Adjacency Matrix representation
Adjacency Matrix representation
Adjacency Matrix representation

Advantages:
• Easy to store and manipulate matrices.
• Finding the cycles and path in a graph is easy.
Disadvantage:
• The space requires for a graph having N vertices is N X N, but the matrix
contain only few elements.
Adjacency Matrix - Algorithm

1. If a graph has n vertices, we use n x n matrix to represent the graph.

2. Let's assume the n x n matrix as adj[n][n].

3. if there is an edge from vertex i to j, mark adj[i][j] as 1. i.e. adj[i][j] == 1

4. if there is no edge from vertex i to j, mark adj[i][j] as 0. i.e. adj[i][j] == 0


C++ Graph Implementation Using Adjacency matrix
#include <iostream>
#include <vector>
#include <stack>
using namespace std;

#define Max_Vertex 100

class Graph {
private:
int Adj_Matrix[Max_Vertex][Max_Vertex]; // Adjacency matrix
int Vertex; // Number of vertices
int Edge; // Number of edges

public:
Graph(); // Constructor
bool IsEmpty();
void Insert_Vertex(int u);
void Insert_Edge(int u, int v);
bool IsEdge(int u, int v);
void Remove_Edge(int u, int v);
void Display();
void DFS(int startVertex);
};
C++ Graph Implementation Using Adjacency matrix

// Constructor
Graph::Graph()
{
Vertex = 0;
Edge = 0;

for (int i = 0; i < Max_Vertex; ++i) {


for (int j = 0; j < Max_Vertex; ++j) {
Adj_Matrix[i][j] = 0;
}
}
}
// Check if the graph is empty
bool Graph::IsEmpty()
{
return Vertex == 0;
}
C++ Graph Implementation Using Adjacency matrix
// Add a vertex to the graph
void Graph::Insert_Vertex(int u)
{
if (u < 0 || u >= Max_Vertex) {
cout << "Invalid vertex index!" << endl;
return;
}

Vertex++;
}

// Add an edge between two vertices


void Graph::Insert_Edge(int u, int v)
{
if (u < 0 || v < 0 || u >= Max_Vertex || v >= Max_Vertex) {
cout << "Invalid vertex indices!" << endl;
return;
}

Adj_Matrix[u][v] = 1;
Adj_Matrix[v][u] = 1; // Assuming an undirected graph
Edge++;
}
C++ Graph Implementation Using Adjacency matrix

// Check if an edge exists between two vertices


bool Graph::IsEdge(int u, int v)
{
return (u >= 0 && v >= 0 && u < Max_Vertex && v < Max_Vertex &&
Adj_Matrix[u][v] == 1);
}

// Remove an edge between two vertices


void Graph::Remove_Edge(int u, int v)
{
if (IsEdge(u, v)) {
Adj_Matrix[u][v] = 0;
Adj_Matrix[v][u] = 0;
Edge--;
}
}
C++ Graph Implementation Using Adjacency matrix

// Display the adjacency matrix


void Graph::Display()
{
cout << "Adjacency Matrix:" << endl;
for (int i = 0; i < Vertex; ++i) {
for (int j = 0; j < Vertex; ++j) {
cout << Adj_Matrix[i][j] << " ";
}
cout << endl;
}
}
C++ Graph Implementation Using Adjacency matrix
int main() {
Graph graph;

// Add vertices
graph.Insert_Vertex(0);
graph.Insert_Vertex(1);
graph.Insert_Vertex(2);
graph.Insert_Vertex(3);

// Add edges
graph.Insert_Edge(0, 1);
graph.Insert_Edge(0, 2);
graph.Insert_Edge(1, 3);
graph.Insert_Edge(2, 3);

// Display the adjacency matrix


graph.Display();

// Perform DFS traversal starting from vertex 0


//graph.DFS(0);

// Remove an edge and display the updated adjacency matrix


graph.Remove_Edge(0, 1);
cout << "After removing edge (0, 1):" << endl;
graph.Display();

return 0;
}
Adjacency List Representation of Graph - Algorithm

• In Adjacency List, we use an array of a list to represent the graph.


• The list size is equal to the number of vertex(n).
• Adjlist[0] will have all the nodes which are connected to vertex 0.
• Adjlist[1] will have all the nodes which are connected to vertex 1 and so on.
Program for lists the class for the node required for adjacency list representation of the
graph.
#include <iostream>
#include <list>
using namespace std;
// Node class for each vertex in the graph
class GraphNode {
public:
int vertex; // Vertex value
int weight; // Weight of the edge
//(default is 0)
// Constructor to initialize a GraphNode
GraphNode(int v, int w = 0) : vertex(v), weight(w) {}
};
// Graph class to represent the graph
class Graph {
public:
int numVertices; // Number of vertices in the graph
list<GraphNode>* adjacencyList; // Array of linked lists to store
adjacency lists

// Constructor to create a graph with a given number of vertices


Graph(int vertices) : numVertices(vertices) {
adjacencyList = new list<GraphNode>[numVertices];
}
// Destructor to free memory allocated for adjacencyList
~Graph() {
delete[] adjacencyList;
}
// Function to add an edge between two vertices with an optional weight
void addEdge(int source, int destination, int weight = 1) {
adjacencyList[source].emplace_back(destination, weight);
adjacencyList[destination].emplace_back(source, weight);
// Assuming undirected graph
}
// Function to display the graph in an adjacency list format
void displayGraph() {
for (int i = 0; i < numVertices; ++i) {
cout << "Vertex " << i << ": ";
for (const auto & node : adjacencyList[i]) {
cout << "(" << node.vertex << ", " << node.weight << ") -> ";
}
cout << "NULL\n";
}}};
int main() {
// Create a graph with 5 vertices
Graph myGraph(5);
// Add edges to the graph
myGraph.addEdge(0, 1, 2);
myGraph.addEdge(0, 3, 1);
myGraph.addEdge(1, 2, 4);
myGraph.addEdge(2, 4, 3);
myGraph.addEdge(3, 4, 5);

// Display the graph


myGraph.displayGraph();

return 0;
}
Multi-list Representation

• In the Multi- list representation of graph structures; these are two parts,

1. A directory of Node information and

2. A set of linked list of edge information.

• There is one entry in the node directory for each node of the graph.

• The directory entry for node i points to a linked adjacency list for node i.

• Each record of the linked list area appears on two adjacency lists: one for the node at

each end of the represented edge.

• In the adjacency list representation of an undirected graph, each edge (vi , vj ) is

represented by two entries, one on the list of vi and the other on the list of vj .
• For the graph G1 in Fig., the edge connecting the vertices 1 and 2 is represented
twice, in the lists of vertices 1 and 2.
• For each edge, there will be exactly one node, but this node will be in two lists, that
is, the adjacency lists for each of the two nodes it is incident on.
• The node structure of such a list can be represented as follows:

• Here, the visited tag is a one bit mark field that indicates whether or not the edge has
been examined.
• This tag would be set accordingly when the edge is processed.
Inverse adjacency list

• An inverse adjacency list is a set of lists that contains one list for each vertex.
• Each list contains a node per vertex adjacent to the vertex it represents.
Graph Traversal -

• To solve many problems modelled with graphs, we need to visit all the vertices and
edges in a systematic fashion called graph traversal.
• There are two types of graph traversal
1. Depth-first traversal and
2. Breadth-first traversal.
• Traversal of a graph is commonly used to search a vertex or an edge through the
graph; hence, it is also called a search technique.
• Consequently, depth-first and breadth-first traversals are popularly known as
depth-first search (DFS) and breadth-first search (BFS), respectively.
Graph Traversal - Depth-first Search (DFS)

• For recursive implementation Depth-first search works by selecting one vertex,

say v of G as a start vertex; v is marked as visited. Then, each unvisited vertex adjacent

to v is searched using the DFS recursively. Once all the vertices that can be reached

from v have been visited, the search for v is complete. If some vertices remain unvisited,

we select an unvisited vertex as a new start vertex and then repeat the process until all

the vertices of G are marked as visited.

• For non-recursive implementation, whenever we reach a node, we shall push it

(vertex or node address) onto the stack. We would then pop the vertex, process it, and

push all its adjacent vertices onto the stack.


Graph Traversal - Depth-first Search (DFS) For recursive implementation
The recursive algorithm for DFS can be outlined as in Algorithm
int main()
{
// number of vertices
int v = 5;

// number of edges
int e = 4;

// adjacency matrix
adj = vector<vector<int> >(v,vector<int>(v, 0));

addEdge(0, 1);
addEdge(0, 2);
addEdge(0, 3);
addEdge(0, 4);

// Visited vector to so that a vertex is not visited more than


once
// Initializing the vector to false as no vertex
//is visited at the beginning
vector<bool> visited(v, false);

// Perform DFS
dfs(0, visited);
}
Graph Traversal - Depth-first Search (DFS) For recursive implementation

// function to perform DFS on the graph


void dfs(int start, vector<bool>& visited)
{
// Print the current node
cout << start << " ";
// Set current node as visited
visited[start] = true;
// For every node of the graph
for (int i = 0; i < adj[start].size(); i++) {
// If some node is adjacent to the current node
// and it has not already been visited
if (adj[start][i] == 1 && (!visited[i])) {
dfs(i, visited);
}
}
}
Graph Traversal - Depth-first Search (DFS) For recursive implementation

// Graph class representing the overall structure


class Graph {
public:
int totalVertices;
vector<list<int>> adjLists; // Adjacency list using vectors

// Constructor to initialize the graph


Graph(int vertices) {
totalVertices = vertices;
adjLists.resize(vertices); // Allocate space for adjacency lists
}

// Function to add an edge to the graph


void addEdge(int src, int dest) {
adjLists[src].push_back(dest); //Add destination to source's
list
adjLists[dest].push_back(src); //Add source to destination's
list

}
// Function to perform DFS traversal
void DFS(int vertex)
{
vector<bool> visited(totalVertices, false); // Visited flag
// array
DFSUtil(vertex, visited);
}

// Recursive helper function for DFS


void DFSUtil(int v, vector<bool>& visited)
{
visited[v] = true;
cout << v << " -> ";

// Iterate through adjacent node


for (int adj_node : adjLists[v]) {
if (!visited[adj_node]) {
DFSUtil(adj_node, visited);
}
}
}
};
Graph Traversal - Depth-first Search (DFS) For recursive implementation

int main() {
int vertices = 8;
Graph graph(vertices);

graph.addEdge(1, 5);
graph.addEdge(1, 2);
graph.addEdge(1, 3);
graph.addEdge(3, 6);
graph.addEdge(2, 7);
graph.addEdge(2, 4);

cout << "The Adjacency List of the Graph is:" << endl;
// Display function can be implemented here for visualization

cout << "DFS traversal of the graph: " << endl;


graph.DFS(1);

return 0;
}
Graph Traversal - Depth-first Search (DFS) For non - recursive implementation
DFS (Depth First Search)

Step 1 - Define a Stack of size total number of vertices in the graph.


Step 2 - Select any vertex as starting point for traversal. Visit that vertex and push it on to
the Stack.
Step 3 - Visit any one of the non-visited adjacent vertices of a vertex which is at the top of
stack and push it on to the stack.
Step 4 - Repeat step 3 until there is no new vertex to be visited from the vertex which is
at the top of the stack.
Step 5 - When there is no new vertex to visit then use back tracking and pop one vertex
from the stack.
Step 6 - Repeat steps 3, 4 and 5 until stack becomes Empty.
Step 7 - When stack becomes Empty, then produce final spanning tree by removing unused
edges from the graph
// Depth-First Search (DFS) non recursive Traversal using adjacency matrix
void Graph::DFS_NR(int startVertex) {
if (startVertex < 0 || startVertex >= Vertex) {
cout << "Invalid start vertex!" << endl;
return;
}
vector<bool> visited(Vertex, false);
stack<int> dfsStack;
cout << "DFS Traversal starting from vertex " << startVertex << ": ";
dfsStack.push(startVertex);
visited[startVertex] = true;
while (!dfsStack.empty()) {
int currentVertex = dfsStack.top();
dfsStack.pop();
cout << currentVertex << " ";
for (int i = 0; i < Vertex; ++i) {
if (Adj_Matrix[currentVertex][i] == 1 && !visited[i]) {
dfsStack.push(i);
visited[i] = true;
}
}
}
// Depth-First Search (DFS) non recursive Traversal using adjacency list
void Graph:: void DFS_NR(int vertex) {
vector<bool> visited(totalVertices, false);
stack<int> stack;
stack.push(vertex);

while (!stack.empty()) {
int v = stack.top();
stack.pop();

if (!visited[v]) {
cout << v << " -> ";
visited[v] = true;

for (int adj_node : adjLists[v]) {


if (!visited[adj_node]) {
stack.push(adj_node);
}
}
}
}
}
};
Example
Breadth-first Search

• Breadth First Search (BFS) is a fundamental graph traversal algorithm. It involves visiting

all the connected nodes of a graph in a level-by-level manner.

• Breadth First Search (BFS) is a graph traversal algorithm that explores all the

vertices in a graph at the current depth before moving on to the vertices at the next

depth level. It starts at a specified vertex and visits all its neighbors before moving on

to the next level of neighbors.

• BFS is commonly used in algorithms for pathfinding, connected components, and

shortest path problems in graphs.


BFS (Breadth First Search)
BFS traversal of a graph produces a spanning tree as final result. Spanning Tree is a
graph without loops. We use Queue data structure with maximum size of total
number of vertices in the graph to implement BFS traversal.
We use the following steps to implement BFS traversal...
• Step 1 - Define a Queue of size total number of vertices in the graph.
• Step 2 - Select any vertex as starting point for traversal. Visit that vertex and
insert it into the Queue.
• Step 3 - Visit all the non-visited adjacent vertices of the vertex which is at front of
the Queue and insert them into the Queue.
• Step 4 - When there is no new vertex to be visited from the vertex which is at
front of the Queue then delete that vertex.
• Step 5 - Repeat steps 3 and 4 until queue becomes empty.
• Step 6 - When queue becomes empty, then produce final spanning tree by
removing unused edges from the graph
Example
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
// Class representing the graph
class Graph {
public:
int V; // Number of vertices
vector<Node*> adjLists;

Graph(int V) : V(V) {
adjLists.resize(V, nullptr); // Allocate space for adjacency
lists
}
// Function for adding an edge to the adjacency matrix

void addEdge(vector<vector<int>>& adjMatrix, int src, int dest) {

if (src >= 0 && src < adjMatrix.size()

&& dest >= 0 && dest < adjMatrix.size()) {

adjMatrix[src][dest] = 1; // Mark edge from src to dest

} else {

cout << "Invalid vertex indices\n";

}
// Function for Breadth-First Search traversal using adjacency matrix
void bfs(const vector<vector<int>>& adjMatrix, int start, int V) {
vector<bool> visited(V, false); // Keeps track of visited nodes
queue<int> q; // Queue for BFS traversal

// Enqueue starting node and mark it visited


q.push(start);
visited[start] = true;

while (!q.empty()) {
int current_node = q.front();
q.pop();

cout << current_node << " -> "; // Visit the current node

// Iterate through adjacent node (using matrix row for current node)
for (int i = 0; i < V; i++) {
if (adjMatrix[current_node][i] == 1 && !visited[i]) {
q.push(i); // Enqueue unvisited adjacent node
visited[i] = true; // Mark neighbor as visited
}
}
}
cout << endl;
}
int main() {
// Sample adjacency matrix (initially no edges)

int V = 5; // Number of vertices


vector<vector<int>> adjMatrix(V, vector<int>(V, 0));
// Add edges using the addEdge function

addEdge(adjMatrix, 0, 1);
addEdge(adjMatrix,0, 2);
addEdge(adjMatrix,1, 2);
addEdge(adjMatrix,2, 0);
addEdge(adjMatrix,2, 3);
addEdge(adjMatrix,3, 4);
cout << "Visited nodes (BFS): ";
bfs(adjMatrix, 0, V); // Start BFS from node 0
return 0;
}
// Function to perform BFS traversal on the graph using adjacency List

void bfs(vector<vector<int>>& adjList, int start) {


int V = adjList.size(); // Number of vertices
vector<bool> visited(V, false); // Keep track of visited nodes
// Create a queue for BFS
queue<int> q;
// Mark the starting vertex as visited and enqueue it
visited[start] = true;
q.push(start);
while (!q.empty()) {
int v = q.front(); // Get the front element from the queue
q.pop();
cout << v << " "; // Process the current vertex
// Iterate through all adjacent vertices of the current vertex
for (int adj_node : adjList[v]) {
if (!visited[adj_node ]) {
visited[adj_node ] = true; // Mark neighbor as visited
q.push(adj_node ; // Enqueue unvisited neighbor
}
Minimum spanning
Tree
• A tree is a connected graph with no cycles.
• A spanning tree is a sub-graph of G that has all vertices of G and is a tree.
• A minimum spanning tree of a weighted graph G is the spanning tree of G whose edges
sum to minimum weight.
• There can be more than one minimum spanning tree for a graph.
• Figure shows a graph, one of its spanning trees, and a minimum spanning tree.
Spanning Tree: Spanning tree of a graph is a tree that includes all the vertices. eg.There

are roads that connect every city.

Minimum Spanning Tree: Minimum Spanning Tree of a weighted graph is a spanning

tree such that the sum of all the weights of the spanning tree is minimum.
Greedy algorithms for computing minimum spanning tree

• The two popular methods used to compute the minimum spanning tree of a graph are
1. Prim’s algorithm
2. Kruskal’s algorithm

Prim’s Algorithm

To implement Prim’s algorithm in finding the minimum spanning tree of a graph, here are
the things to be in mind:
1. All the vertices of the graph must be included
2. The vertex with the minimum weight(distance) must be selected first. All the vertices
must be connected
3. There must be no cycle
Prim’s Algorithm Steps

Step-1:
1. Randomly choose any vertex.
2. The vertex connecting to the edge having least weight is usually selected.
Step-2:
3. Find all the edges that connect the tree to new vertices.
4. Find the least weight edge among those edges and include it in the existing tree.
5. If including that edge creates a cycle, then reject that edge and look for the next
least weight edge.
Step-3:
6. Keep repeating step-2 until all the vertices are included and Minimum Spanning
Tree (MST) is obtained.
Algorithm for Prim's Minimum Spanning Tree

Below we have the complete logic, stepwise, which is followed in prim's algorithm:

Step 1: Keep a track of all the vertices that have been visited and added to the spanning
tree.

Step 2: Create the spanning tree and Initially the spanning tree is empty.

Step 3: Choose a random vertex, and add it to the spanning tree. This becomes the root
node.

Step 4: Add a new vertex, say x, such that

1. x is not in the already built spanning tree.


2. x is connected to the built spanning tree using minimum weight edge. (Thus, x can
be adjacent to any of the nodes that have already been added in the spanning tree).
3. Adding x to the spanning tree should not form cycles.

Step 5: Repeat the Step 4, till all the vertices of the graph are added to the spanning tree.

Step 6: Print the total cost of the spanning tree.


C++ implementation of Prim's Algorithm

#include<iostream>
using namespace std;
// Number of vertices in the graph
const int V=6;
// Function to find the vertex with minimum key value
int min_Key(int key[], bool visited[])
{
int min = 999, min_index; // 999 represents an Infinite value

for (int v = 0; v < V; v++)


{
if (visited[v] == false && key[v] < min)
{
// vertex should not be visited
min = key[v];
min_index = v;
}
}
return min_index;
}
// Function to print the final MST stored in parent[]
int print_MST(int parent[], int cost[V][V])
{
int minCost=0;
cout<<"Edge \tWeight\n";
for (int i = 1; i< V; i++)
{
cout<<parent[i]<<"-"<<i<<"\t"<<cost[i][parent[i]]<<" \n";
minCost+=cost[i][parent[i]];
}
cout<<"Total cost is"<<minCost;
}
// Function to find the MST using adjacency cost matrix
//representation
void find_MST(int cost[V][V])
{
int parent[V], key[V];
bool visited[V];
// Initialize all the arrays
for (int i = 0; i< V; i++) {
key[i] = 999; // 999 represents an Infinite value
visited[i] = false;
parent[i]=-1;
}
key[0] = 0; // Include first vertex in MST by setting its key
//value to 0.
parent[0] = -1; // First node is always root of MST
// The MST will have maximum V-1 vertices
for(int x = 0; x < V-1; x++)
{
//Finding the minimum key vertex from the set of
//vertices not yet included in MST
int u = min_Key(key, visited);
visited[u] = true; // Add the minimum key vertex to the MST
// Update key and parent arrays
for (int v = 0; v < V; v++)
{
// cost[u][v] is non zero only for adjacent vertices of u visited[v]
is false for //vertices not yet included in MST key[] gets updated
only if cost[u][v] is smaller //than key[v]
if (cost[u][v]!=0 && visited[v] == false && cost[u][v] <
key[v])
{
parent[v] = u;
key[v] = cost[u][v];
}
}
}

// print the final MST


print_MST(parent, cost);
}
// main function
int main()
{
int cost[V][V];
cout<<"Enter the vertices for a graph with 6 vetices";
for (int i=0;i<V;i++)
{
for(int j=0;j<V;j++)
{
cin>>cost[i][j];
}
}
find_MST(cost);

return 0;
}
Example for Prim's Minimum Spanning Tree Algorithm

Let's try to trace the above algorithm for finding the Minimum Spanning Tree for the graph
in Fig
Step A:
• Define key[] array for storing the key value(weight
or distance or cost) of every vertex. Initialize this to
∞(infinity) for all the vertices.
• Define another array Boolean visited[] for keeping a
track of all the vertices that have been added to the
spanning tree. Initially this will be 0 for all the
vertices, since the spanning tree is empty.
• Define an array parent[] for keeping track of the
parent vertex. Initialize this to -1 for all the vertices.
• Initialize minimum cost, minCost = 0
Step B:
Choose any random vertex, say f and set key[f]=0.

Since its key value is minimum and it is not visited,


add f to the spanning tree.

Also, update the following:


minCost = 0 + key[f] = 0
This is how the visited[] array will look like:

Key values for all the adjacent vertices of f will look


like this (key value is nothing but the cost or the
weight of the edge, for (f,d) it is still infinity because
they are not directly connected):

There will be no change in the parent[] because f is


the root node.
Step C:
• The arrays key[] and visited[] will be searched for finding the next vertex.
• f has the minimum key value but will not be considered since it is already added
(visited[f]==1)
• Next vertex having the minimum key value is c. Since visited[c]==0, it will be added
to the spanning tree.

Again, update the following:


minCost = 0 + key[c] = 0 + 1 = 1
This is how the visited[] array will look like:

And, the parent[] array (f becomes the parent of c):

For every adjacent vertex of c, say v, values in key[v] will be


updated using the formula:
key[v] = min(key[v], cost[c][v])
Thus the key[] array will become:
Step D:
Repeat the Step C for the remaining
vertices. Next vertex to be selected is a.
And minimum cost will become
minCost=1+2=3

Next, either b or d can be selected. Let's


consider b. Then the minimum cost will
become minCost=3+3=6

Next vertex to be selected is d,

making the minimum cost

minCost=6+3=9
Then, e is selected and the minimum cost will become, minCost=9+2=11

• Since all the vertices have been visited now, the algorithm terminates.
• Thus, Fig. 21 represents the Minimum Spanning Tree with total cost=11.
Minimum Spanning Tree Using Kruskal Algorithm

• Kruskal's algorithm for finding the Minimum Spanning Tree(MST), which finds an edge

of the least possible weight that connects any two trees in the forest

• It is a greedy algorithm.

• It finds a subset of the edges that forms a tree that includes every vertex, where the

total weight of all the edges in the tree is minimized.

• If the graph is not connected, then it finds a minimum spanning forest (a minimum

spanning tree for each connected component).

• Number of edges in MST:V-1 (V – no of vertices in Graph).


How this algorithm works?

1. Sort the edges in ascending order of weights.

2. Pick the edge with the least weight. Check if including this edge in spanning tree will

form a cycle is Yes then ignore it if No then add it to spanning tree.

3. Repeat the step 2 till spanning tree has V-1 (V – no of vertices in Graph).

4. Spanning tree with least weight will be formed, called Minimum Spanning Tree
Union-Find Disjoint Sets data structure

• A Union-Find data structure can be used to maintain knowledge of the connected


components of a graph, and query for them quickly.
• Operations
• make set → creates a new set. Sets are tree DS
• union → merges the sets of two items into one
• find → returns the set representative/leader for which the item belongs

Make Set - At this point, every object is a set representative.


Union - A union operation on A and C
deletes set-3 and merges C into set-1. A is
still the set representative, but C’s parent
pointer now points to A.

Find - The find operation returns the set


representative for which an object is
contained . Find on ‘F’ will return Set 1’s
representative i.e. ‘A’
Pseudo Code:

// Initialize result
mst_weight = 0
// Create V single item sets
for each vertex v
parent[v] = v;
rank[v] = 0;
Sort all edges into non decreasing order by weight w
for each (u, v) taken from the sorted list E
do if FIND-SET(u) != FIND-SET(v)
print edge(u, v)
mst_weight += weight of edge(u, v)
UNION(u, v)
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++)
{
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.begin(), edges.end()); // Sort edges in increasing order on basis of cost
DisjointSets ds(V); // Create disjoint sets
vector< pair<int, iPair> >::iterator it; // Iterate through all sorted edges
for (it=edges.begin(); it!=edges.end(); it++)
{
int u = it->second.first; // iterators second members first element
int v = it->second.second; // iterators secong members second element
int set_u = ds.find(u);
int set_v = ds.find(v);
//Check if the selected edge is creating a cycle or not
//Cycle is created if u and v belong to same set
if (set_u != set_v)
{
cout << u << " - " << v << endl; //Current edge will be in the MST so print it
mst_wt += it->first; // Update MST weight
ds.merge(set_u, set_v); // Merge two sets
}
}
// Driver program to test above functions
int main()
{
/* Let us create above shown weighted
and undirected graph */
int V = 9, E = 14;
Graph g(V, E);

// 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);

cout << "Edges of MST are \n";


int mst_wt = g.kruskalMST();

cout << "\nWeight of MST is " << mst_wt;

return 0;
}
Dikjtra's Single source shortest path

• Dijkstra Algorithm is an algorithm for finding the shortest path from a source node

to all other nodes in a graph(single source shortest path).

• It is a type of greedy algorithm. It only works on weighted graphs with positive

weights.

• It has a time complexity of O(V2) using the adjacency matrix representation of

graph.

• The time complexity can be reduced to O((V+E)log V) using adjacency list

representation of graph, where E is the number of edges in the graph and V is the

number of vertices in the graph.


Basics of Dijkstra's Algorithm

• Dijkstra's Algorithm basically starts at the node that you choose (the source node) and

it analyzes the graph to find the shortest path between that node and all the other

nodes in the graph.

• The algorithm keeps track of the currently known shortest distance from each node to

the source node and it updates these values if it finds a shorter path.

• Once the algorithm has found the shortest path between the source node and another

node, that node is marked as "visited" and added to the path.

• The process continues until all the nodes in the graph have been added to the path.

This way, we have a path that connects the source node to all other nodes following

the shortest path possible to reach each node.


Algorithm for Dijkstra’s Algorithm:

1. Mark the source node with a current distance of 0 and the rest with infinity.

2. Set the non-visited node with the smallest current distance as the current node.

3. For each neighbor, N of the current node adds the current distance of the adjacent

node with the weight of the edge connecting 0->1. If it is smaller than the current

distance of Node, set it as the new current distance of N.

4. Mark the current node 1 as visited.

5. Go to step 2 if there are any nodes are unvisited.


Dijkstra Algorithm - pseudo code

function Dijkstra(Graph, source):

for each vertex v in Graph:


distance[v] = infinity

distance[source] = 0
G = the set of all nodes of the Graph

while G is non-empty:
Q = node in G with the least dist[ ]
mark Q visited
for each neighbor N of Q:
alt_dist = distance[Q] + dist_between(Q, N)
if alt-dist < distance[N]
distance[N] := alt_dist
Example of Dijkstra's Algorithm

Generate the shortest path from node 0 to all the other nodes in the graph.
Since we are choosing to start at node 0, we can mark this node as visited.

Now we need to start checking the distance from node 0 to its adjacent nodes. As you
can see, these are nodes 1 and 2 (see the red edges):
After updating the distances of the adjacent nodes, we need to:
1. Select the node that is closest to the source node based on the current known
distances.
2. Mark it as visited.
3. Add it to the path.

If we check the list of distances, we can see that node 1 has the shortest distance to the
source node (a distance of 2), so we add it to the path.

We mark it with a red square in the list to represent


that it has been "visited" and that we have found the
shortest path to this node:
• Now we need to analyze the new adjacent nodes to find the shortest path to reach
them. We will only analyze the nodes that are adjacent to the nodes that are already part
of the shortest path.
• Node 3 and node 2 are both adjacent to nodes that are already in the path because they
are directly connected to node 1 and node 0, respectively

For node 3: the total distance is 7 because we add the weights of the edges that form the
path 0 -> 1 -> 3
Now that we have the distance to the adjacent nodes, we have to choose which node will
be added to the path. We must select the unvisited node with the shortest (currently
known) distance to the source node.

From the list of distances, we can immediately detect that this is node 2 with distance 6:
We also mark it as visited in the list of distances and crossing it off from the list of
unvisited nodes:

Now we need to repeat the process to find the shortest path from the source node to
the new adjacent node, which is node 3.
You can see that we have two possible paths 0 -> 1 -> 3 or 0 -> 2 -> 3.
We need to check the new adjacent nodes that we have not visited so far. This time, these
nodes are node 4 and node 5 since they are adjacent to node 3.

We update the distances of these nodes to the source node, always trying to find a shorter
path, if possible:
• For node 4: the distance is 17 from the path 0 -> 1 -> 3 -> 4.
• For node 5: the distance is 22 from the path 0 -> 1 -> 3 -> 5.
We need to choose which unvisited node will be marked as visited now. In this case, it's
node 4 because it has the shortest distance in the list of distances. We also mark it as
"visited" by adding a small red square in the list. And we cross it off from the list of
unvisited nodes.
And we repeat the process again. We check the adjacent nodes: node 5 and node 6. We
need to analyze each possible path that we can follow to reach them from nodes that
have already been marked as visited and added to the path.

For node 5:
1. The first option is to follow the path 0 -> 1 -> 3 -> 5, which has a distance of 22 from
the source node (2 + 5 + 15). This distance was already recorded in the list of
distances in a previous step.
2. The second option would be to follow the path 0 -> 1 -> 3 -> 4 -> 5, which has a
distance of 23 from the source node (2 + 5 + 10 + 6).
3. Clearly, the first path is shorter, so we choose it for node 5
For node 6:
The path available is 0 -> 1 -> 3 -> 4 -> 6, which has a distance of 19 from the source
node (2 + 5 + 10 + 2).

We mark the node with the shortest


(currently known) distance as visited. In this
case, node 6. And we cross it off from the list
of unvisited nodes.
Now we have this path (marked in red):
Only one node has not been visited yet, node 5. Let's see how we can include it in the path.

There are three different paths that we can take to reach node 5 from the nodes that have
been added to the path:

1. Option 1: 0 -> 1 -> 3 -> 5 with a distance of 22 (2 + 5 + 15).


2. Option 2: 0 -> 1 -> 3 -> 4 -> 5 with a distance of 23 (2 + 5 + 10 + 6).
3. Option 3: 0 -> 1 -> 3 -> 4 -> 6 -> 5 with a distance of 25 (2 + 5 + 10 + 2 + 6).
We select the shortest path: 0 -> 1 -> 3 -> 5 with a distance of 22.
We mark the node as visited and cross it off from the list of unvisited nodes
Algorithm:
1. Create a set sptSet (shortest path tree set) that keeps track of vertices included in the shortest
path tree, i.e., whose minimum distance from the 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 the distance value as 0 for the source vertex so that it is picked first.
3. While sptSet doesn’t include all vertices
• Pick a vertex u that is not there in sptSet and has a minimum distance value.
• Include u to sptSet.
• Then update the distance value of all adjacent vertices of u.
1. To update the distance values, iterate through all adjacent vertices.
2. For every adjacent vertex v, if the sum of the 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.
#include <iostream>
using namespace std;
#include <limits.h>

#define V 6 // Number of vertices in the graph

//Function to find the vertex with minimum distance


int minDist(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;
}
//Function to print the constructed distance array
void printSolution(int distance[])
{
cout <<"Vertex \t Distance from Source" << endl;
for (int i = 0; i < V; i++)
cout << (char)(i+65) << " \t\t"<<distance[i]<< endl;
}
// Function that implements Dijkstra's algorithm
void dijkstra(int graph[V][V], int src)
{
int distance[V]; //initializing output array
bool sptSet[V]; // list of visited nodes
// Initializing all distances as INFINITE and sptSet[] as false
for (int i = 0; i < V; i++)
distance[i] = INT_MAX, sptSet[i] = false;
// Setting distance of source as 0
distance[src] = 0;
// Find shortest path for all vertices
for (int count = 0; count < V - 1; count++) {
//calling minDistance to pick next vertex
int u = minDist(distance, sptSet);
// Mark the picked vertex as visited
sptSet[u] = true;
//Relaxing all neighbours of U
for (int v = 0; v < V; v++)
if (!sptSet[v] && graph[u][v] && distance[u] != INT_MAX
&& distance[u] + graph[u][v] < distance[v])
distance[v] = distance[u] + graph[u][v];
}
// print the constructed distance array
printSolution(distance);
}
// driver function
int main()
{

//Example graph
//Same as Graph in example diagram above

int graph[V][V] = { {0,4,5,0,0,0},


{4,0,11,9,7,0},
{5,11,0,0,3,0},
{0,9,0,0,13,2},
{0,7,3,13,0,6},
{0,0,0,2,6,0}};
int source=0;
dijkstra(graph, source);

return 0;
}
All pairs shortest paths- Floyd-Warshall Algorithm

• The Floyd Warshall Algorithm is an algorithm that solves the all-pairs shortest path

problem in a weighted graph.

• The algorithm calculates the shortest path between all pairs of vertices in a graph.

• It is unique because it can handle negative edge weights and graphs with cycles.

• The algorithm works by constructing a matrix of the shortest distances between all

pairs of vertices in the graph.


How Floyd Warshall Algorithm works:
• The Floyd Warshall Algorithm works by constructing a matrix of the shortest distances
between all pairs of vertices in the graph.
• The algorithm initially sets the distance between each vertex and itself as zero.
• Then it iteratively computes the shortest path between each pair of vertices, using the
formula:
distance[i][j] = min(distance[i][j], distance[i][k] + distance[k][j])
where i, j, and k are vertices in the graph, and distance[i][j] represents the shortest
distance between i and j.

• The algorithm repeats this process for all vertices in the graph, and eventually, the
resulting matrix will contain the shortest distance between all pairs of vertices.
Algorithm : Floyd-Warshall
1. Create a two-dimensional array of size n x n for storing the length of the shortest path between all
node pairs.
n is the number of nodes in the graph.
Initialize all the cells of this array with ∞.
2. For every node i in the graph, initialize the distance of the node to itself as 0.
Distance [ i ] [ i ] = 0.
3. For every edge ( u, v ) in the graph, initialize the distance array as the weight of the edge.
Distance [ u ] [ v ] = Weight of (u, v)
4. For every node k in [ 1 … n ] do
For every node i in [ 1 … n ] do
For every node j in [ 1 … n ] do
If ( Distance [ i ] [ j ] > Distance [ i ] [ k ] + Distance [ k ] [ j ] ) :
Distance [ i ] [ j ] = Distance [ i ] [ k ] + Distance [ k ] [ j ]
Advantages and Disadvantages
Advantages:
1. The Floyd Warshall Algorithm is easy to understand and implement.
2. It can handle negative edge weights and graphs with cycles.
3. It can solve problems involving a large number of nodes in the graph.
Disadvantages:
1. The algorithm has a high time complexity of O(V³), where V is the number of vertices in
the graph.
2. The algorithm requires a large amount of memory to store the distance matrix.
3. The algorithm does not work well for very large graphs.
Example Walkthrough
Let’s walk through an example using a simple graph with 4 nodes (A, B, C, D) and the
following weighted edges:

A to B: 3

A to D: 7

B to C: 1

C to D: 2

D to B: 5

The graph can be represented as an adjacency matrix:

Where "∞" represents that there is no direct path

between the nodes.


Step 1: Initialization
Initialize the dist[][] matrix as the adjacency matrix of the
graph.

Step 2: Iteration through all nodes (k)


• For each node k, consider it as an intermediate node, and
update the shortest paths.

Iteration with k = A:

Update distances considering A as an intermediate node:

• No updates needed as there are no shorter paths through


A.

Iteration with k = B:

Update distances considering B as an intermediate node:

• dist[A][C] = min(dist[A][C], dist[A][B] + dist[B][C]) =


min(∞, 3 + 1) = 4

• dist[D][C] remains unchanged as there is no shorter path.


Iteration with k = C:
Update distances considering C as an intermediate node:
•dist[A][D] = min(dist[A][D], dist[A][C] + dist[C][D]) = min(7, 4 + 2) = 6

•dist[B][D] = min(dist[B][D], dist[B][C] + dist[C][D]) = min(∞, 1 + 2) = 3

Updated matrix:
Iteration with k = D:
Update distances considering D as an intermediate node:
• dist[A][B] and dist[C][B] remain unchanged as there are no shorter paths through
D.
#include <iostream>
#include <vector>
#include <bits/stdc++.h>

using namespace std;

void floyd_warshall(vector<vector<int>>& dist, const int V)


{
for (int k=0; k < V; k++)
{
for (int i=0; i < V; i++)
{
for (int j=0; j < V; j++)
{
if (dist[i][k] != INT_MAX && dist[k][j] != INT_MAX)
dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
}
}
}
}
void addEdge(vector<vector<int>>& dist,int u, int v, int w)
{
dist[u][v] = w;
}
int main()
{
int V = 5;
vector<vector<int>> dist(V, vector<int> (V, INT_MAX));

addEdge(dist, 0, 1, 3);
addEdge(dist, 0, 4, -4);
addEdge(dist, 0, 2, 8);
addEdge(dist, 1, 3, 1);
addEdge(dist, 1, 4, 7);
addEdge(dist, 2, 1, 4);
addEdge(dist, 3, 0, 2);
addEdge(dist, 3, 2, -5);
addEdge(dist, 4, 3, 6);
for (int i=0; i < V; i++)
dist[i][i] = 0;

floyd_warshall(dist, V);
cout << "Shortest distance between all pairs: " << endl;
for (int i=0; i < V; i++)
for (int j=0; j < V; j++)
cout << i << "," << j << " : " << dist[i][j] << endl;
cout << endl;

return 0;
}
Topological Sort/Ordering
• Topological sorting for Directed Acyclic Graph (DAG) is a linear ordering of vertices

such that for every directed edge u-v, vertex u comes before v in the ordering.

• A topological ordering is only possible in directed acyclic graph(DAG).

• Any DAG can have more than one topological orderings.

• Topological sort is a graph traversal that every node in the graph is visited until all of its

dependencies are visited.

• Only directed acyclic graph(DAG) can have topological orderings which can align all the

nodes in a linear line.

• A directed graph without cycles can have multiple topological orderings.


• The first vertex in topological sorting is always a vertex with an in-degree of 0 (a
vertex with no incoming edges).
• A topological sorting of the following graph is “5 4 2 3 1 0”.
• There can be more than one topological sorting for a graph. Another topological
sorting of the following graph is “4 5 2 3 1 0”.
Algorithm for Topological Sorting using DFS:
1. Create a graph with n vertices and m-directed edges.
2. Initialize a stack and a visited array of size n.
3. For each unvisited vertex in the graph, do the following:
• Call the DFS function with the vertex as the parameter.
• In the DFS function, mark the vertex as visited and recursively call the DFS
function for all unvisited neighbors of the vertex.
• Once all the neighbors have been visited, push the vertex onto the stack.
4. After all, vertices have been visited, pop elements from the stack and append them to
the output list until the stack is empty.
5. The resulting list is the topologically sorted order of the graph.
Topological Sorting Algorithm using DFS:
// Function to perform DFS and topological sorting
void topologicalSortUtil(int v, vector<vector<int> >& adj,
vector<bool>& visited,
stack<int>& Stack)
{
// Mark the current node as visited
visited[v] = true;

// Recur for all adjacent vertices


for (int i : adj[v]) {
if (!visited[i])
topologicalSortUtil(i, adj, visited, Stack);
}

// Push current vertex to stack which stores the result


Stack.push(v);
}
Topological Sorting Algorithm using DFS:

// Function to perform Topological Sort


void topologicalSort(vector<vector<int> >& adj, int V)
{
stack<int> Stack; // Stack to store the result
vector<bool> visited(V, 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])
topologicalSortUtil(i, adj, visited, Stack);
}

// Print contents of stack


while (!Stack.empty()) {
cout << Stack.top() << " ";
Stack.pop();
}
}
Advantages of Topological Sort:

1. Helps in scheduling tasks or events based on dependencies.

2. Detects cycles in a directed graph.

3. Efficient for solving problems with precedence constraints.

Disadvantages of Topological Sort:

1. Only applicable to directed acyclic graphs (DAGs), not suitable for cyclic graphs.

2. May not be unique, multiple valid topological orderings can exist.

3. Inefficient for large graphs with many nodes and edges.


Kahn’s algorithm for Topological Sorting

Algorithm:
1. Add all nodes with in-degree 0 to a queue.
2. While the queue is not empty:
3. Remove a node from the queue.
4. For each outgoing edge from the removed node, decrement the in-degree of the
destination node by 1.
5. If the in-degree of a destination node becomes 0, add it to the queue.
6. If the queue is empty and there are still nodes in the graph, the graph contains a
cycle and cannot be topologically sorted.
7. The nodes in the queue represent the topological ordering of the graph.
Kahn’s algorithm for Topological Sorting
Kahn’s algorithm for Topological Sorting

// Function to return list containing vertices in Topological


order.
vector<int> topologicalSort(vector<vector<int> >& adj,
int V)
{
// Vector to store indegree of each vertex
vector<int> indegree(V);
for (int i = 0; i < V; i++) {
for (auto it : adj[i]) {
indegree[it]++;
}
}

// Queue to store vertices with indegree 0


queue<int> q;
for (int i = 0; i < V; i++) {
if (indegree[i] == 0) {
q.push(i);
}
}
vector<int> result;
while (!q.empty()) {
int node = q.front();
q.pop();
result.push_back(node);

// Decrease indegree of adjacent vertices as the


//current node is in topological order

for (auto it : adj[node]) {


indegree[it]--;

// If indegree becomes 0, push it to the queue


if (indegree[it] == 0)
q.push(it);
}
}

// Check for cycle


if (result.size() != V) {
cout << "Graph contains cycle!" << endl;
return {};
}

return result;
}

You might also like