One of the most powerful data structures in Computer Science.
| Application | Vertex | Edge |
|---|---|---|
| User | Friendship | |
| Google Maps | City | Road |
| Computer Network | Computer | Cable |
G = (V, E)
V = Set of Vertices
E = Set of Edges
A vertex represents an object or entity.
Vertices = {A, B, C, D}
Examples: Person, City, Computer
An edge represents a relationship or connection.
(A,B) (A,C) (B,D) (C,D)
Examples: Friendship, Road, Communication Link
Degree(v) = Number of edges connected to v
A → B → D
A sequence of connected vertices.
Length = Number of edges.
A → B → C → A
Starts and ends at the same vertex.
Cycles are important in routing and networking.
Every vertex can reach every other vertex.
Some vertices cannot be reached.
| Term | Description |
|---|---|
| Vertex | Node in a graph |
| Edge | Connection between vertices |
| Degree | Number of incident edges |
| Path | Sequence of connected vertices |
| Cycle | Closed path |
Graphs can be classified based on direction, weights, connectivity, cycles and structure.
Edges have no direction.
A ----- B
If A is connected to B, then B is also connected to A.
Friendship network example.
Edges have directions.
A → B
Connection is one-way.
Twitter follows relationship.
A → B → C
| Vertex | In-Degree | Out-Degree |
|---|---|---|
| A | 0 | 1 |
| B | 1 | 1 |
| C | 1 | 0 |
| Feature | Undirected | Directed |
|---|---|---|
| Direction | No | Yes |
| Degree | Degree | In/Out Degree |
| Example | Friendship | Twitter Follow |
Each edge has an associated cost, distance, time, or weight.
A --5-- B
Common in routing and shortest-path problems.
Weight may represent distance (km).
All edges are considered equal.
A ----- B ----- C
Only connectivity matters.
| Feature | Weighted | Unweighted |
|---|---|---|
| Edge Cost | Present | Absent |
| Complexity | Higher | Lower |
| Example | Road Network | Social Network |
Every vertex is connected to every other vertex.
Kₙ
Maximum possible number of edges.
Every pair of vertices is connected.
Number of Edges = n(n − 1) / 2
| Vertices | Edges |
|---|---|
| 4 | 6 |
| 5 | 10 |
| 6 | 15 |
A graph with vertices but no edges.
No vertex is connected.
Every vertex can be reached from every other vertex.
All vertices reachable
Only one connected component exists.
Contains multiple connected components.
Some vertices cannot reach others.
A graph containing at least one cycle.
A → B → C → A
Start from a vertex and return to it.
Cycle: A → B → C → A
A graph that contains no cycles.
A → B → C → D
Impossible to return to the starting vertex.
Directed Graph + No Cycles
DAG = Directed Acyclic Graph
Very important in AI, Scheduling and Compilers.
No directed cycle exists.
Vertices can be divided into two disjoint sets.
U ∩ V = ∅
Edges only connect vertices from different sets.
Student ↔ Course registration network
A tree is a special graph that:
Every tree is a graph, but not every graph is a tree.
| Type | Key Property |
|---|---|
| Undirected | No direction |
| Directed | Has direction |
| Weighted | Edge costs |
| Complete | All vertices connected |
| Bipartite | Two vertex sets |
| DAG | No directed cycle |
| Tree | Connected + Acyclic |
How do we store graphs inside a computer?
A graph must be stored efficiently inside computer memory.
Three common representations:
Edges: (A,B) (A,C) (B,D) (C,D)
A two-dimensional matrix used to represent graph connections.
Matrix Size = V × V
Rows = Source Vertex
Columns = Destination Vertex
| Vertex | Index |
|---|---|
| A | 0 |
| B | 1 |
| C | 2 |
| D | 3 |
| A | B | C | D | |
|---|---|---|---|---|
| A | 0 | 0 | 0 | 0 |
| B | 0 | 0 | 0 | 0 |
| C | 0 | 0 | 0 | 0 |
| D | 0 | 0 | 0 | 0 |
| A | B | C | D | |
|---|---|---|---|---|
| A | 0 | 1 | 0 | 0 |
| B | 1 | 0 | 0 | 0 |
| C | 0 | 0 | 0 | 0 |
| D | 0 | 0 | 0 | 0 |
Because graph is undirected.
(A,C) (B,D) (C,D)
Continue updating the matrix.
| A | B | C | D | |
|---|---|---|---|---|
| A | 0 | 1 | 1 | 0 |
| B | 1 | 0 | 0 | 1 |
| C | 1 | 0 | 0 | 1 |
| D | 0 | 1 | 1 | 0 |
matrix[A][B] = 1
A is connected to B.
matrix[A][D] = 0
A is not connected to D.
A → B
| A | B | |
|---|---|---|
| A | 0 | 1 |
| B | 0 | 0 |
Not symmetric.
A --5-- B
| A | B | |
|---|---|---|
| A | 0 | 5 |
| B | 5 | 0 |
Store edge weights instead of 1.
AdjacencyMatrix(V, edges[]):
// Initialization
Create matrix[V][V] filled with 0
// Add each edge
for each edge (u, v) in edges[]:
matrix[u][v] = 1
matrix[v][u] = 1 // undirected graph
// Edge Check: O(1)
hasEdge(u, v):
return matrix[u][v] == 1
// Add Edge: O(1)
addEdge(u, v):
matrix[u][v] = 1
matrix[v][u] = 1
// Remove Edge: O(1)
removeEdge(u, v):
matrix[u][v] = 0
matrix[v][u] = 0
#include <stdio.h>
#include <string.h>
#define MAX 10
int V; // Number of vertices
int matrix[MAX][MAX]; // Adjacency matrix
// Initialize matrix to all zeros
void initGraph(int vertices) {
V = vertices;
memset(matrix, 0, sizeof(matrix));
}
// Add undirected edge between u and v
void addEdge(int u, int v) {
matrix[u][v] = 1;
matrix[v][u] = 1; // Remove this line for directed graph
}
// Remove edge between u and v
void removeEdge(int u, int v) {
matrix[u][v] = 0;
matrix[v][u] = 0;
}
// Check if edge exists: O(1)
int hasEdge(int u, int v) {
return matrix[u][v] == 1;
}
// Print the adjacency matrix
void printMatrix() {
printf("Adjacency Matrix:\n");
for (int i = 0; i < V; i++) {
for (int j = 0; j < V; j++)
printf("%d ", matrix[i][j]);
printf("\n");
}
}
int main() {
initGraph(4); // Vertices: 0(A), 1(B), 2(C), 3(D)
addEdge(0, 1); // A-B
addEdge(0, 2); // A-C
addEdge(1, 3); // B-D
addEdge(2, 3); // C-D
printMatrix();
return 0;
}
#include <stdio.h>
#include <string.h>
#include <limits.h>
#define MAX 10
#define INF INT_MAX
int V;
int wMatrix[MAX][MAX]; // Weighted adjacency matrix
void initWeightedGraph(int vertices) {
V = vertices;
for (int i = 0; i < V; i++)
for (int j = 0; j < V; j++)
wMatrix[i][j] = (i == j) ? 0 : INF; // 0 on diagonal
}
// Add weighted undirected edge
void addWeightedEdge(int u, int v, int weight) {
wMatrix[u][v] = weight;
wMatrix[v][u] = weight;
}
void printWeightedMatrix() {
printf("Weighted Adjacency Matrix:\n");
for (int i = 0; i < V; i++) {
for (int j = 0; j < V; j++) {
if (wMatrix[i][j] == INF) printf("INF ");
else printf("%3d ", wMatrix[i][j]);
}
printf("\n");
}
}
How can a graph be stored inside computer memory?
Vertices A B C D Edges (A,B) (A,C) (B,D) (C,D)
We will represent this graph in different ways.
A 2D matrix of size V × V.
Rows represent source vertices.
Columns represent destination vertices.
| A | B | C | D | |
|---|---|---|---|---|
| A | 0 | 1 | 1 | 0 |
| B | 1 | 0 | 0 | 1 |
| C | 1 | 0 | 0 | 1 |
| D | 0 | 1 | 1 | 0 |
| Operation | Complexity |
|---|---|
| Check Edge | O(1) |
| Add Edge | O(1) |
| Delete Edge | O(1) |
| Space | O(V²) |
Best for Dense Graphs
Rows represent vertices.
Columns represent edges.
| E1 | E2 | E3 | E4 | |
|---|---|---|---|---|
| A | 1 | 1 | 0 | 0 |
| B | 1 | 0 | 1 | 0 |
| C | 0 | 1 | 0 | 1 |
| D | 0 | 0 | 1 | 1 |
IncidenceMatrix(V, E, edges[]):
// Create V × E matrix filled with 0
Create incMatrix[V][E] = 0
// For each edge ej = (u, v) at index j:
for j = 0 to E-1:
u, v = edges[j]
incMatrix[u][j] = 1 // vertex u is incident to edge j
incMatrix[v][j] = 1 // vertex v is incident to edge j
// Find all edges of a vertex u: scan row u
getEdges(u):
for j = 0 to E-1:
if incMatrix[u][j] == 1: output edge j
#include <stdio.h>
#include <string.h>
#define MAX_V 10
#define MAX_E 20
int V, E;
int incMatrix[MAX_V][MAX_E]; // incidence matrix
void initIncidenceMatrix(int vertices, int edges) {
V = vertices;
E = edges;
memset(incMatrix, 0, sizeof(incMatrix));
}
// Add edge j between vertex u and v
void addEdge(int j, int u, int v) {
incMatrix[u][j] = 1;
incMatrix[v][j] = 1;
}
void printIncidenceMatrix() {
printf("Incidence Matrix (V x E):\n");
printf(" ");
for (int j = 0; j < E; j++) printf("E%d ", j);
printf("\n");
char labels[] = "ABCD";
for (int i = 0; i < V; i++) {
printf("%c ", labels[i]);
for (int j = 0; j < E; j++)
printf(" %d ", incMatrix[i][j]);
printf("\n");
}
}
int main() {
// Graph: A-B(E0), A-C(E1), B-D(E2), C-D(E3)
initIncidenceMatrix(4, 4);
addEdge(0, 0, 1); // E0: A-B
addEdge(1, 0, 2); // E1: A-C
addEdge(2, 1, 3); // E2: B-D
addEdge(3, 2, 3); // E3: C-D
printIncidenceMatrix();
return 0;
}
Each vertex stores a list of its neighbors.
A → B → C B → A → D C → A → D D → B → C
A : B, C B : A, D C : A, D D : B, C
Only existing edges are stored.
| Operation | Complexity |
|---|---|
| Space | O(V + E) |
| Add Edge | O(1) |
| Traverse Neighbors | Efficient |
Best for Sparse Graphs — O(V+E) space
AdjacencyList(V, edges[]):
// Create array of lists, one per vertex
Create list adj[V]
// Add each edge
for each edge (u, v) in edges[]:
adj[u].append(v)
adj[v].append(u) // undirected
// Add Edge: O(1)
addEdge(u, v):
adj[u].append(v)
adj[v].append(u)
// Remove Edge: O(degree)
removeEdge(u, v):
adj[u].remove(v)
adj[v].remove(u)
// Get all neighbors of u: O(degree(u))
getNeighbors(u):
return adj[u]
#include <stdio.h>
#include <stdlib.h>
#define MAX_V 10
#define MAX_NEIGHBORS 10
int V;
int adjList[MAX_V][MAX_NEIGHBORS];
int degree[MAX_V]; // number of neighbors per vertex
void initGraph(int vertices) {
V = vertices;
for (int i = 0; i < V; i++) degree[i] = 0;
}
// Add undirected edge u-v
void addEdge(int u, int v) {
adjList[u][degree[u]++] = v;
adjList[v][degree[v]++] = u;
}
// Print adjacency list
void printAdjList() {
char labels[] = "ABCD";
printf("Adjacency List:\n");
for (int i = 0; i < V; i++) {
printf("%c: ", labels[i]);
for (int j = 0; j < degree[i]; j++)
printf("%c ", labels[adjList[i][j]]);
printf("\n");
}
}
int main() {
initGraph(4);
addEdge(0, 1); // A-B
addEdge(0, 2); // A-C
addEdge(1, 3); // B-D
addEdge(2, 3); // C-D
printAdjList();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
// Node in the linked list
typedef struct Node {
int vertex;
struct Node* next;
} Node;
// Graph structure
typedef struct Graph {
int V;
Node** adjList; // array of linked list heads
} Graph;
// Create a new graph
Graph* createGraph(int V) {
Graph* g = malloc(sizeof(Graph));
g->V = V;
g->adjList = malloc(V * sizeof(Node*));
for (int i = 0; i < V; i++) g->adjList[i] = NULL;
return g;
}
// Create a new adjacency list node
Node* newNode(int v) {
Node* n = malloc(sizeof(Node));
n->vertex = v; n->next = NULL;
return n;
}
// Add undirected edge u--v
void addEdge(Graph* g, int u, int v) {
// Add v to u's list
Node* n = newNode(v);
n->next = g->adjList[u];
g->adjList[u] = n;
// Add u to v's list
n = newNode(u);
n->next = g->adjList[v];
g->adjList[v] = n;
}
void printGraph(Graph* g) {
char labels[] = "ABCD";
for (int v = 0; v < g->V; v++) {
printf("%c: ", labels[v]);
Node* cur = g->adjList[v];
while (cur) { printf("%c ", labels[cur->vertex]); cur = cur->next; }
printf("\n");
}
}
int main() {
Graph* g = createGraph(4);
addEdge(g, 0, 1); addEdge(g, 0, 2);
addEdge(g, 1, 3); addEdge(g, 2, 3);
printGraph(g);
return 0;
}
| Feature | Matrix | List |
|---|---|---|
| Space | O(V²) | O(V+E) |
| Edge Search | O(1) | O(degree) |
| Dense Graph | Excellent | Good |
| Sparse Graph | Poor | Excellent |
| Application | Preferred Representation |
|---|---|
| Adjacency List | |
| Google Maps | Adjacency List |
| Dense Communication Network | Adjacency Matrix |
Common operations performed on graphs.
InsertVertex(G, v):
// For Adjacency Matrix:
Expand matrix to (V+1) × (V+1)
Initialize new row and column to 0
V = V + 1
// For Adjacency List:
Add new empty list adj[v]
V = V + 1
Complexity: Matrix O(V²) (resize) | List O(1)
// --- Adjacency Matrix approach ---
#include <stdio.h>
#include <string.h>
#define MAX 10
int V = 0;
int matrix[MAX][MAX];
void insertVertex() {
// New vertex gets index V
for (int i = 0; i <= V; i++) {
matrix[V][i] = 0; // new row
matrix[i][V] = 0; // new column
}
V++; // increment vertex count
printf("Vertex inserted. Total vertices: %d\n", V);
}
// --- Adjacency List approach ---
#define MAX_V 10
int adjList[MAX_V][MAX_V];
int degree[MAX_V];
int Vlist = 0;
void insertVertexList() {
degree[Vlist] = 0; // empty adjacency list
Vlist++;
printf("Vertex inserted. Total vertices: %d\n", Vlist);
}
InsertEdge(G, u, v):
// For Adjacency Matrix:
matrix[u][v] = 1
matrix[v][u] = 1 // undirected only
// Complexity: O(1)
// For Adjacency List:
adj[u].append(v)
adj[v].append(u) // undirected only
// Complexity: O(1)
#include <stdio.h>
#define MAX 10
int V;
int matrix[MAX][MAX];
// Insert edge in Adjacency Matrix: O(1)
void insertEdgeMatrix(int u, int v) {
if (u >= V || v >= V) {
printf("Invalid vertices!\n");
return;
}
matrix[u][v] = 1;
matrix[v][u] = 1; // remove for directed graph
printf("Edge (%d, %d) inserted.\n", u, v);
}
// --- Adjacency List approach ---
int adjList[MAX][MAX];
int degree[MAX];
// Insert edge in Adjacency List: O(1)
void insertEdgeList(int u, int v) {
adjList[u][degree[u]++] = v;
adjList[v][degree[v]++] = u;
printf("Edge (%d, %d) inserted.\n", u, v);
}
DeleteEdge(G, u, v):
// For Adjacency Matrix:
matrix[u][v] = 0
matrix[v][u] = 0 // undirected only
// Complexity: O(1)
// For Adjacency List:
adj[u].remove(v)
adj[v].remove(u) // undirected only
// Complexity: O(degree(u) + degree(v))
#include <stdio.h>
#define MAX 10
int V;
int matrix[MAX][MAX];
// Delete edge from Adjacency Matrix: O(1)
void deleteEdgeMatrix(int u, int v) {
matrix[u][v] = 0;
matrix[v][u] = 0;
printf("Edge (%d, %d) deleted.\n", u, v);
}
// --- Adjacency List ---
int adjList[MAX][MAX];
int degree[MAX];
// Delete edge from Adjacency List: O(degree)
void deleteEdgeList(int u, int v) {
// Remove v from u's list
for (int i = 0; i < degree[u]; i++) {
if (adjList[u][i] == v) {
adjList[u][i] = adjList[u][--degree[u]];
break;
}
}
// Remove u from v's list
for (int i = 0; i < degree[v]; i++) {
if (adjList[v][i] == u) {
adjList[v][i] = adjList[v][--degree[v]];
break;
}
}
printf("Edge (%d, %d) deleted.\n", u, v);
}
DeleteVertex(G, v):
// For Adjacency Matrix:
// Set entire row v and column v to 0
for i = 0 to V-1:
matrix[v][i] = 0
matrix[i][v] = 0
// (Then optionally shift rows/columns)
V = V - 1
// Complexity: O(V)
// For Adjacency List:
// Remove v from every neighbor's list
for each u in adj[v]:
adj[u].remove(v)
adj[v] = empty
V = V - 1
// Complexity: O(V + E)
All incident edges are also removed.
#include <stdio.h>
#define MAX 10
int V;
int matrix[MAX][MAX];
// Delete vertex v from Adjacency Matrix: O(V)
void deleteVertexMatrix(int v) {
// Clear row v and column v
for (int i = 0; i < V; i++) {
matrix[v][i] = 0;
matrix[i][v] = 0;
}
printf("Vertex %d deleted (all its edges cleared).\n", v);
}
// --- Adjacency List approach ---
int adjList[MAX][MAX];
int degree[MAX];
// Delete vertex v from Adjacency List: O(V+E)
void deleteVertexList(int v) {
// Remove v from all neighbor lists
for (int i = 0; i < degree[v]; i++) {
int u = adjList[v][i];
for (int j = 0; j < degree[u]; j++) {
if (adjList[u][j] == v) {
adjList[u][j] = adjList[u][--degree[u]];
break;
}
}
}
degree[v] = 0; // clear v's list
printf("Vertex %d deleted.\n", v);
}
// Search for an Edge (u, v)
SearchEdge(G, u, v):
// Adjacency Matrix: O(1)
if matrix[u][v] == 1: return true
else: return false
// Adjacency List: O(degree(u))
for each w in adj[u]:
if w == v: return true
return false
// Search for a Vertex v
SearchVertex(G, v):
// Matrix/List: O(1) if vertices are indexed
if 0 <= v < V: return true
else: return false
#include <stdio.h>
#define MAX 10
int V;
int matrix[MAX][MAX];
// Check if edge exists — Adjacency Matrix: O(1)
int searchEdgeMatrix(int u, int v) {
if (u < V && v < V)
return matrix[u][v] == 1;
return 0; // invalid
}
// Check if vertex is valid: O(1)
int searchVertex(int v) {
return (v >= 0 && v < V);
}
// --- Adjacency List ---
int adjList[MAX][MAX];
int degree[MAX];
// Check if edge exists — Adjacency List: O(degree(u))
int searchEdgeList(int u, int v) {
for (int i = 0; i < degree[u]; i++)
if (adjList[u][i] == v) return 1;
return 0;
}
int main() {
V = 4;
matrix[0][1] = matrix[1][0] = 1; // A-B
matrix[0][2] = matrix[2][0] = 1; // A-C
printf("Edge A-B exists: %d\n", searchEdgeMatrix(0, 1));
printf("Edge A-D exists: %d\n", searchEdgeMatrix(0, 3));
printf("Vertex 3 exists: %d\n", searchVertex(3));
return 0;
}
Traversal means visiting every vertex of a graph systematically.
Breadth First Search
Uses Queue
Depth First Search
Uses Stack / Recursion
Visit all neighbors first.
Breadth First Search explores vertices level by level.
Nearest vertices first
FIFO First In First Out
The first vertex inserted is processed first.
"Breadth-first search is one of the simplest algorithms for searching a graph... it expands the frontier between discovered and undiscovered vertices uniformly across the breadth of the frontier. That is, the algorithm discovers all vertices at distance k from s before discovering any vertices at distance k+1."
— Introduction to Algorithms (CLRS)
Visited:
A
, B
, C
, D
, E
, F
, G
Queue:
BFS(graph, start):
create a queue Q
mark start as visited
enqueue start into Q
while Q is not empty:
current = dequeue from Q
process(current)
for each neighbor of current:
if neighbor is not visited:
mark neighbor as visited
enqueue neighbor into Q
#include <stdio.h>
#include <stdlib.h>
#define MAX_VERTICES 100
int queue[MAX_VERTICES];
int front = 0, rear = 0;
void enqueue(int vertex) { queue[rear++] = vertex; }
int dequeue() { return queue[front++]; }
int isQueueEmpty() { return front == rear; }
void BFS(int graph[MAX_VERTICES][MAX_VERTICES], int start, int numVertices) {
int visited[MAX_VERTICES] = {0};
visited[start] = 1;
enqueue(start);
printf("BFS Traversal: ");
while (!isQueueEmpty()) {
int current = dequeue();
printf("%d ", current);
for (int i = 0; i < numVertices; i++) {
if (graph[current][i] == 1 && !visited[i]) {
visited[i] = 1;
enqueue(i);
}
}
}
printf("\n");
}
Time: O(V + E)
Space: O(V)
V = Vertices, E = Edges
Go deep before exploring siblings.
"The strategy followed by depth-first search is, as its name implies, to search 'deeper' in the graph whenever possible. Depth-first search explores edges out of the most recently discovered vertex v that still has unexplored edges leaving it."
— Introduction to Algorithms (CLRS)
Visited:
A
, B
, D
, E
, C
, F
, G
Stack:
DFS(graph, start):
create a stack S
push start to S
while S is not empty:
current = pop from S
if current is not visited:
mark current as visited
process(current)
for each neighbor of current in reverse order:
if neighbor is not visited:
push neighbor to S
#include <stdio.h>
#define MAX_VERTICES 100
int visited[MAX_VERTICES] = {0};
void DFS(int graph[MAX_VERTICES][MAX_VERTICES], int vertex, int numVertices) {
// Mark the current node as visited and print it
visited[vertex] = 1;
printf("%d ", vertex);
// Recur for all the vertices adjacent to this vertex
for (int i = 0; i < numVertices; i++) {
if (graph[vertex][i] == 1 && !visited[i]) {
DFS(graph, i, numVertices);
}
}
}
| Feature | BFS | DFS |
|---|---|---|
| Data Structure | Queue (FIFO) | Stack (LIFO) / Recursion |
| Traversal Approach | Level by Level | Deepest Node First |
| Optimal For | Shortest Path (Unweighted) | Cycle Detection, Mazes |
| Memory | More (stores levels) | Less (stores path) |
Before understanding Minimum Spanning Trees, we must first understand Spanning Trees.
Consider the following connected graph.
The graph contains multiple paths between vertices.
A spanning tree is obtained by removing edges without disconnecting the graph.
Every connected graph can have multiple spanning trees.
A graph may have many different spanning trees.
Which one should we choose?
Each edge has an associated cost (weight).
Weight 4 + 2 + 5 + 6 + 7 = 24
Weight 1 + 2 + 4 + 5 + 6 = 18
Both graphs are valid spanning trees because they:
A Minimum Spanning Tree (MST) is a spanning tree whose total edge weight is the smallest among all possible spanning trees.
| Property | Value |
|---|---|
| Connected | ✔ |
| Cycle Free | ✔ |
| Weighted Graph | ✔ |
| Edges | V − 1 |
| Minimum Cost | ✔ |
Yes.
If different spanning trees have the same minimum total weight, they are all valid Minimum Spanning Trees.
Tree A Weight = 15 Tree B Weight = 15 Both are MSTs
Searching every possible spanning tree is inefficient.
A Greedy Algorithm makes the best local decision at every step, hoping to obtain the global optimum.
Always choose the lowest-cost edge that does NOT create a cycle.
Instead of growing from one vertex, Kruskal grows the MST by selecting edges in increasing order.
Original Weighted Graph
| Edge | Weight |
|---|---|
| C — F | 1 |
| A — D | 2 |
| D — E | 3 |
| A — B | 4 |
| B — E | 5 |
| B — C | 6 |
| E — F | 7 |
Sorted Edge: C — F (Weight = 1)
No cycle is formed, so the edge is accepted.
Yes. B → A → D → E already connects B and E.
| Selected Edge | Weight |
|---|---|
| C — F | 1 |
| A — D | 2 |
| D — E | 3 |
| A — B | 4 |
| B — C | 6 |
Exactly V − 1 = 5 edges were selected.
No cycles were formed.
The selected edges are highlighted in green. The rejected edge (B–E) is shown in red dashed.
| Selected Edge | Weight |
|---|---|
| A — D | 2 |
| D — E | 3 |
| A — B | 4 |
| B — C | 6 |
| C — F | 1 |
| Total Cost | 16 |
KRUSKAL(Graph G)
1. Sort all edges in ascending order of weight
2. Create an empty Minimum Spanning Tree (MST)
3. For each edge (u, v) in sorted order
if Find(u) ≠ Find(v)
Add edge to MST
Union(u, v)
4. Stop when MST contains V - 1 edges
5. Return MST
Unlike Kruskal's Algorithm (which sorts all edges globally and picks the smallest valid edge anywhere), Prim's Algorithm starts from a single source vertex and gradually grows one connected tree by adding the cheapest edge connecting the tree to an unvisited node.
| Kruskal's Algorithm | Prim's Algorithm |
|---|---|
| Edge-based greedy approach | Vertex-based greedy approach |
| Sorts all graph edges globally upfront | Grows one connected tree node by node |
| Can maintain multiple disconnected component trees | Maintains a single connected tree at all times |
| Uses Union-Find (Disjoint Set) for cycle detection | Uses Visited array / Priority Queue |
| Best for Sparse Graphs (E ≪ V2) | Best for Dense Graphs (E ≈ V2) |
Starting Vertex: A
| Candidate Edge | Weight | Action |
|---|---|---|
| A ➔ D | 2 | Select ✓ |
| A ➔ B | 4 | Keep |
| Candidate Edge | Weight | Action |
|---|---|---|
| D ➔ E | 3 | Select ✓ |
| A ➔ B | 4 | Keep |
| Candidate Edge | Weight | Action |
|---|---|---|
| A ➔ B | 4 | Select ✓ |
| E ➔ B | 5 | Skip |
| E ➔ F | 7 | Keep |
| Candidate Edge | Weight | Action |
|---|---|---|
| B ➔ C | 6 | Select ✓ |
| B ➔ E | 5 | Reject (Cycle) |
| E ➔ F | 7 | Keep |
| Candidate Edge | Weight | Action |
|---|---|---|
| C ➔ F | 1 | Select ✓ |
| E ➔ F | 7 | Reject (Cycle) |
| Selected Edge | Weight |
|---|---|
| C – F | 1 |
| A – D | 2 |
| D – E | 3 |
| A – B | 4 |
| B – C | 6 |
| Total MST Weight | 16 |
#include <stdio.h>
#include <stdbool.h>
#define V 6
#define INF 999999
int minKey(int key[], bool mstSet[]) {
int min = INF, min_index = -1;
for (int v = 0; v < V; v++)
if (mstSet[v] == false && key[v] < min)
min = key[v], min_index = v;
return min_index;
}
void primMST(int graph[V][V]) {
int parent[V]; // Array to store constructed MST
int key[V]; // Key values used to pick minimum weight edge
bool mstSet[V]; // To represent set of vertices included in MST
for (int i = 0; i < V; i++)
key[i] = INF, mstSet[i] = false;
key[0] = 0; // Make key 0 so that vertex 0 is picked first
parent[0] = -1; // First node is always root of MST
for (int count = 0; count < V - 1; count++) {
int u = minKey(key, mstSet);
mstSet[u] = true;
for (int v = 0; v < V; v++)
if (graph[u][v] && mstSet[v] == false && graph[u][v] < key[v])
parent[v] = u, key[v] = graph[u][v];
}
}
Single Source Shortest Path (SSSP) Algorithm for Weighted Graphs
The Shortest Path between vertex S and vertex T is the path whose sum of edge weights is minimized.
| Possible Path A ➔ D | Cost |
|---|---|
| A ➔ B ➔ D (4 + 3) | 7 |
| A ➔ C ➔ D (2 + 1) | 3 ✓ |
Computes fastest driving route between map coordinates (Google Maps / Waze).
Routers compute minimum latency paths for network packets across backbones.
Calculates collision-free shortest trajectories for autonomous mobile robots.
Optimizes multi-stop delivery vehicle dispatch routes to reduce fuel costs.
NPC pathfinding across complex grid maps (A* algorithm variant).
Finds cheapest multi-leg flight connections across airport hub networks.
| Minimum Spanning Tree (MST) | Shortest Path (Dijkstra) |
|---|---|
| Connects all vertices together | Finds path between source and target(s) |
| Minimizes total weight of the entire tree | Minimizes individual path weight from source |
| Always uses exactly V − 1 edges | Uses variable number of edges per path |
| Algorithms: Prim's, Kruskal's | Algorithms: Dijkstra's, Bellman-Ford |
| Global network optimization (e.g. power grid) | Point-to-point routing (e.g. GPS navigation) |
If going to vertex v through vertex u is shorter than the current known distance to v, we relax the edge (u, v):
Source Vertex: A
| Edge | Weight |
|---|---|
| A–D | 1 |
| A–C | 2 |
| A–B | 4 |
| B–E | 3 |
| B–C | 5 |
| D–E | 6 |
| C–E | 8 |
| Vertex | Distance | Previous |
|---|---|---|
| A | 0 | - |
| B | ∞ | - |
| C | ∞ | - |
| D | ∞ | - |
| E | ∞ | - |
| Vertex | Distance | Previous |
|---|---|---|
| A (Done) | 0 | - |
| D | 1 | A |
| C | 2 | A |
| B | 4 | A |
| E | ∞ | - |
| Vertex | Distance | Previous |
|---|---|---|
| A (Done) | 0 | - |
| D (Done) | 1 | A |
| C | 2 | A |
| B | 4 | A |
| E | 7 | D |
| Vertex | Distance | Previous |
|---|---|---|
| A (Done) | 0 | - |
| D (Done) | 1 | A |
| C (Done) | 2 | A |
| B | 4 | A |
| E | 7 | D |
| Vertex | Distance | Previous |
|---|---|---|
| A (Done) | 0 | - |
| D (Done) | 1 | A |
| C (Done) | 2 | A |
| B (Done) | 4 | A |
| E | 7 | D |
| Target Vertex | Shortest Distance | Shortest Path |
|---|---|---|
| A | 0 | A |
| D | 1 | A ➔ D |
| C | 2 | A ➔ C |
| B | 4 | A ➔ B |
| E | 7 | A ➔ D ➔ E |
dist = [A:0, B:4, C:2, D:1, E:7]
#include <stdio.h>
#include <stdbool.h>
#define V 5
#define INF 999999
int minDistance(int dist[], bool sptSet[]) {
int min = INF, 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;
}
void dijkstra(int graph[V][V], int src) {
int dist[V];
bool sptSet[V];
for (int i = 0; i < V; i++)
dist[i] = INF, sptSet[i] = false;
dist[src] = 0;
for (int count = 0; count < V - 1; count++) {
int u = minDistance(dist, sptSet);
if (u == -1) break;
sptSet[u] = true;
for (int v = 0; v < V; v++)
if (!sptSet[v] && graph[u][v] && dist[u] != INF
&& dist[u] + graph[u][v] < dist[v])
dist[v] = dist[u] + graph[u][v];
}
}
| Implementation | Time Complexity | Space Complexity | Best For |
|---|---|---|---|
| Adjacency Matrix + Array | O(V2) | O(V) | Dense Graphs (E ≈ V2) |
| Adjacency List + Min-Heap / PQ | O((V + E) log V) | O(V + E) | Sparse Graphs (E ≪ V2) |
| Adjacency List + Fibonacci Heap | O(E + V log V) | O(V + E) | Theoretical Optimum |