Total number of Spanning Trees in a Graph
Last Updated :
08 Jun, 2025
If a graph is a complete graph with n vertices, then total number of spanning trees is n(n-2) where n is the number of nodes in the graph. In complete graph, the task is equal to counting different labeled trees with n nodes for which have Cayley's formula.
What if Graph is not Complete?
Follow the below given procedure based on Kirchhoff's theorem
- STEP 1: Create Adjacency Matrix for the given graph.
- STEP 2: Replace all the diagonal elements with the degree of nodes. For eg. element at (1, 1) position of adjacency matrix will be replaced by the degree of node 1, element at (2, 2) position of adjacency matrix will be replaced by the degree of node 2, and so on.
- STEP 3: Replace all non-diagonal 1's with -1.
- STEP 4: Calculate co-factor for any element.
- STEP 5: The cofactor that you get is the total number of spanning tree for that graph.
Consider the following graph:
Adjacency Matrix for the above graph will be as follows:

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.
Let's see another example to solve these problems by making use of the Laplacian matrix.
A Laplacian matrix L, where
L[i, i] is the degree of node i and L[i, j] = -1 if there is an edge between nodes i and j,
and otherwise L[i, j] = 0.
Kirchhoff’s theorem provides a way to calculate the number of spanning trees for a given graph as a determinant of a special matrix.
Consider the following graph,
the undirected graphAll possible spanning trees are as follows
three spanning treesIn order to calculate the number of spanning trees, construct a Laplacian matrix L, where L[i, i] is the degree of node i and L[i, j] = 1 if there is an edge between nodes i and j, and otherwise L[i, j] = 0.
for the above graph, The Laplacian matrix will look like this
The number of spanning trees equals the determinant of a matrix.
The Determinant of a matrix that can be obtained when we remove any row and any column from L.
For example, if we remove the first row and column, the result will be,
The determinant is always the same, regardless of which row and column we remove from L.
Note: Cayley’s formula is a special case of Kirchhoff’s theorem because, in a complete graph of n nodes, the determinant is equal to nn-2
C++
// C++ program to count number of spanning
// trees using matrix exponentiation
#include <bits/stdc++.h>
using namespace std;
// Function to perform matrix multiplication: c = a * b
void multiply(vector<vector<int>> &a, vector<vector<int>> &b,
vector<vector<int>> &c, int v) {
int mod = 1e9 + 7;
vector<vector<int>> temp(v, vector<int>(v, 0));
// Triple nested loop for matrix
// multiplication
for (int i = 0; i < v; i++) {
for (int j = 0; j < v; j++) {
for (int k = 0; k < v; k++) {
temp[i][j] = (temp[i][j] +
1LL * a[i][k] * b[k][j] % mod) % mod;
}
}
}
// Store the result back
// into matrix c
c = temp;
}
// Function to raise matrix a to power n and store in res
void power(vector<vector<int>> &a, int n,
vector<vector<int>> &res, int v) {
int mod = 1e9 + 7;
// Initialize res as identity matrix
for (int i = 0; i < v; i++) {
for (int j = 0; j < v; j++) {
res[i][j] = (i == j);
}
}
vector<vector<int>> temp(v, vector<int>(v, 0));
// Binary exponentiation
while (n > 0) {
if (n % 2 == 1) {
multiply(a, res, temp, v);
res = temp;
}
n /= 2;
multiply(a, a, temp, v);
a = temp;
}
}
// Function to compute number of spanning trees
// using adjacency matrix
int numOfSpanningTree(vector<vector<int>> &graph, int v) {
int mod = 1e9 + 7;
vector<vector<int>> res(v, vector<int>(v, 0));
// Create a copy of the input
// graph as matrix will be modified
vector<vector<int>> temp = graph;
// Raise matrix to (v - 2) power
power(temp, v - 2, res, v);
// Compute the sum of all values in
// the resulting matrix
int ans = 0;
for (int i = 0; i < v; i++) {
for (int j = 0; j < v; j++) {
ans = (ans + res[i][j]) % mod;
}
}
return ans;
}
// Driver code
int main() {
int v = 4;
int e = 5;
vector<vector<int>> graph = {
{0, 1, 1, 1},
{1, 0, 1, 1},
{1, 1, 0, 1},
{1, 1, 1, 0}
};
cout << numOfSpanningTree(graph, v);
return 0;
}
Java
// Java program to count number of spanning
// trees using matrix exponentiation
import java.util.*;
class GfG {
// Function to perform matrix multiplication: c = a * b
static void multiply(int[][] a, int[][] b, int[][] c, int v) {
int mod = (int)1e9 + 7;
int[][] temp = new int[v][v];
// Triple nested loop for matrix
// multiplication
for (int i = 0; i < v; i++) {
for (int j = 0; j < v; j++) {
for (int k = 0; k < v; k++) {
temp[i][j] = (int)((temp[i][j] +
1L * a[i][k] * b[k][j] % mod) % mod);
}
}
}
// Store the result back
// into matrix c
for (int i = 0; i < v; i++) {
for (int j = 0; j < v; j++) {
c[i][j] = temp[i][j];
}
}
}
// Function to raise matrix a to power n and store in res
static void power(int[][] a, int n, int[][] res, int v) {
int mod = (int)1e9 + 7;
// Initialize res as identity matrix
for (int i = 0; i < v; i++) {
for (int j = 0; j < v; j++) {
res[i][j] = (i == j) ? 1 : 0;
}
}
int[][] temp = new int[v][v];
// Binary exponentiation
while (n > 0) {
if (n % 2 == 1) {
multiply(a, res, temp, v);
for (int i = 0; i < v; i++) {
for (int j = 0; j < v; j++) {
res[i][j] = temp[i][j];
}
}
}
n /= 2;
multiply(a, a, temp, v);
for (int i = 0; i < v; i++) {
for (int j = 0; j < v; j++) {
a[i][j] = temp[i][j];
}
}
}
}
// Function to compute number of spanning trees
// using adjacency matrix
static int numOfSpanningTree(int[][] graph, int v) {
int mod = (int)1e9 + 7;
int[][] res = new int[v][v];
// Create a copy of the input
// graph as matrix will be modified
int[][] temp = new int[v][v];
for (int i = 0; i < v; i++) {
for (int j = 0; j < v; j++) {
temp[i][j] = graph[i][j];
}
}
// Raise matrix to (v - 2) power
power(temp, v - 2, res, v);
// Compute the sum of all values in
// the resulting matrix
int ans = 0;
for (int i = 0; i < v; i++) {
for (int j = 0; j < v; j++) {
ans = (ans + res[i][j]) % mod;
}
}
return ans;
}
public static void main(String[] args) {
int v = 4;
int e = 5;
int[][] graph = {
{0, 1, 1, 1},
{1, 0, 1, 1},
{1, 1, 0, 1},
{1, 1, 1, 0}
};
System.out.println(numOfSpanningTree(graph, v));
}
}
Python
# Python program to count number of spanning
# trees using matrix exponentiation
# Function to perform matrix multiplication: c = a * b
def multiply(a, b, c, v):
mod = int(1e9) + 7
temp = [[0] * v for _ in range(v)]
# Triple nested loop for matrix
# multiplication
for i in range(v):
for j in range(v):
for k in range(v):
temp[i][j] = (temp[i][j] +
a[i][k] * b[k][j] % mod) % mod
# Store the result back
# into matrix c
for i in range(v):
for j in range(v):
c[i][j] = temp[i][j]
# Function to raise matrix a to power n and store in res
def power(a, n, res, v):
mod = int(1e9) + 7
# Initialize res as identity matrix
for i in range(v):
for j in range(v):
res[i][j] = 1 if i == j else 0
temp = [[0] * v for _ in range(v)]
# Binary exponentiation
while n > 0:
if n % 2 == 1:
multiply(a, res, temp, v)
for i in range(v):
for j in range(v):
res[i][j] = temp[i][j]
n //= 2
multiply(a, a, temp, v)
for i in range(v):
for j in range(v):
a[i][j] = temp[i][j]
# Function to compute number of spanning trees
# using adjacency matrix
def numOfSpanningTree(graph, v):
mod = int(1e9) + 7
res = [[0] * v for _ in range(v)]
# Create a copy of the input
# graph as matrix will be modified
temp = [row[:] for row in graph]
# Raise matrix to (v - 2) power
power(temp, v - 2, res, v)
# Compute the sum of all values in
# the resulting matrix
ans = 0
for i in range(v):
for j in range(v):
ans = (ans + res[i][j]) % mod
return ans
# Driver code
if __name__ == "__main__":
v = 4
e = 5
graph = [
[0, 1, 1, 1],
[1, 0, 1, 1],
[1, 1, 0, 1],
[1, 1, 1, 0]
]
print(numOfSpanningTree(graph, v))
C#
// C# program to count number of spanning
// trees using matrix exponentiation
using System;
class GfG {
// Function to perform matrix multiplication: c = a * b
static void multiply(int[,] a, int[,] b, int[,] c, int v) {
int mod = (int)1e9 + 7;
int[,] temp = new int[v, v];
// Triple nested loop for matrix
// multiplication
for (int i = 0; i < v; i++) {
for (int j = 0; j < v; j++) {
for (int k = 0; k < v; k++) {
temp[i, j] = (int)((temp[i, j] +
1L * a[i, k] * b[k, j] % mod) % mod);
}
}
}
// Store the result back
// into matrix c
for (int i = 0; i < v; i++) {
for (int j = 0; j < v; j++) {
c[i, j] = temp[i, j];
}
}
}
// Function to raise matrix a to power n and store in res
static void power(int[,] a, int n, int[,] res, int v) {
// Initialize res as identity matrix
for (int i = 0; i < v; i++) {
for (int j = 0; j < v; j++) {
res[i, j] = (i == j) ? 1 : 0;
}
}
int[,] temp = new int[v, v];
// Binary exponentiation
while (n > 0) {
if (n % 2 == 1) {
multiply(a, res, temp, v);
for (int i = 0; i < v; i++) {
for (int j = 0; j < v; j++) {
res[i, j] = temp[i, j];
}
}
}
n /= 2;
multiply(a, a, temp, v);
for (int i = 0; i < v; i++) {
for (int j = 0; j < v; j++) {
a[i, j] = temp[i, j];
}
}
}
}
// Function to compute number of spanning trees
// using adjacency matrix
static int numOfSpanningTree(int[,] graph, int v) {
int mod = (int)1e9 + 7;
int[,] res = new int[v, v];
// Create a copy of the input
// graph as matrix will be modified
int[,] temp = new int[v, v];
for (int i = 0; i < v; i++) {
for (int j = 0; j < v; j++) {
temp[i, j] = graph[i, j];
}
}
// Raise matrix to (v - 2) power
power(temp, v - 2, res, v);
// Compute the sum of all values in
// the resulting matrix
int ans = 0;
for (int i = 0; i < v; i++) {
for (int j = 0; j < v; j++) {
ans = (ans + res[i, j]) % mod;
}
}
return ans;
}
static void Main() {
int v = 4;
int[,] graph = {
{0, 1, 1, 1},
{1, 0, 1, 1},
{1, 1, 0, 1},
{1, 1, 1, 0}
};
Console.WriteLine(numOfSpanningTree(graph, v));
}
}
JavaScript
// JavaScript program to count number of spanning
// trees using matrix exponentiation
// Function to perform matrix multiplication: c = a * b
function multiply(a, b, c, v) {
let mod = 1e9 + 7;
let temp = Array.from({ length: v }, () =>
Array(v).fill(0)
);
// Triple nested loop for matrix
// multiplication
for (let i = 0; i < v; i++) {
for (let j = 0; j < v; j++) {
for (let k = 0; k < v; k++) {
temp[i][j] = (temp[i][j] +
a[i][k] * b[k][j] % mod) % mod;
}
}
}
// Store the result back
// into matrix c
for (let i = 0; i < v; i++) {
for (let j = 0; j < v; j++) {
c[i][j] = temp[i][j];
}
}
}
// Function to raise matrix a to power n and store in res
function power(a, n, res, v) {
let mod = 1e9 + 7;
// Initialize res as identity matrix
for (let i = 0; i < v; i++) {
for (let j = 0; j < v; j++) {
res[i][j] = (i === j) ? 1 : 0;
}
}
let temp = Array.from({ length: v }, () =>
Array(v).fill(0)
);
// Binary exponentiation
while (n > 0) {
if (n % 2 === 1) {
multiply(a, res, temp, v);
for (let i = 0; i < v; i++) {
for (let j = 0; j < v; j++) {
res[i][j] = temp[i][j];
}
}
}
n = Math.floor(n / 2);
multiply(a, a, temp, v);
for (let i = 0; i < v; i++) {
for (let j = 0; j < v; j++) {
a[i][j] = temp[i][j];
}
}
}
}
// Function to compute number of spanning trees
// using adjacency matrix
function numOfSpanningTree(graph, v) {
let mod = 1e9 + 7;
let res = Array.from({ length: v }, () =>
Array(v).fill(0)
);
// Create a copy of the input
// graph as matrix will be modified
let temp = graph.map(row => row.slice());
// Raise matrix to (v - 2) power
power(temp, v - 2, res, v);
// Compute the sum of all values in
// the resulting matrix
let ans = 0;
for (let i = 0; i < v; i++) {
for (let j = 0; j < v; j++) {
ans = (ans + res[i][j]) % mod;
}
}
return ans;
}
// Driver code
let v = 4;
let e = 5;
let graph = [
[0, 1, 1, 1],
[1, 0, 1, 1],
[1, 1, 0, 1],
[1, 1, 1, 0]
];
console.log(numOfSpanningTree(graph, v));
Time Complexity: O(v³*log(v)), due to repeated matrix multiplications for exponentiation. The program calculates the number of spanning trees in a graph using Matrix Tree Theorem, which involves computing the determinant of a matrix derived from the Laplacian matrix of the graph. In some approaches, this includes raising a matrix to the power of (v - 2), where v is the number of vertices.
Each matrix multiplication takes O(v³) time, and if matrix exponentiation is used efficiently (via exponentiation by squaring), the total number of multiplications is O(logn) where n = v - 2.
Space Complexity: O(v²), for storing the matrices and temporary result. The main space is used to store the adjacency matrix and any intermediate matrices during multiplication. Since each matrix is of size v × v.
Conclusion
This approach is generally feasible for small to medium-sized graphs, but may become inefficient for very large graphs due to the high time and space requirements.
Similar Reads
Graph Algorithms Graph is a non-linear data structure like tree data structure. The limitation of tree is, it can only represent hierarchical data. For situations where nodes or vertices are randomly connected with each other other, we use Graph. Example situations where we use graph data structure are, a social net
3 min read
Introduction to Graph Data Structure Graph Data Structure is a non-linear data structure consisting of vertices and edges. It is useful in fields such as social network analysis, recommendation systems, and computer networks. In the field of sports data science, graph data structure can be used to analyze and understand the dynamics of
15+ min read
Graph and its representations A Graph is a non-linear data structure consisting of vertices and edges. The vertices are sometimes also referred to as nodes and the edges are lines or arcs that connect any two nodes in the graph. More formally a Graph is composed of a set of vertices( V ) and a set of edges( E ). The graph is den
12 min read
Types of Graphs with Examples A graph is a mathematical structure that represents relationships between objects by connecting a set of points. It is used to establish a pairwise relationship between elements in a given set. graphs are widely used in discrete mathematics, computer science, and network theory to represent relation
9 min read
Basic Properties of a Graph A Graph is a non-linear data structure consisting of nodes and edges. The nodes are sometimes also referred to as vertices and the edges are lines or arcs that connect any two nodes in the graph. The basic properties of a graph include: Vertices (nodes): The points where edges meet in a graph are kn
4 min read
Applications, Advantages and Disadvantages of Graph Graph is a non-linear data structure that contains nodes (vertices) and edges. A graph is a collection of set of vertices and edges (formed by connecting two vertices). A graph is defined as G = {V, E} where V is the set of vertices and E is the set of edges. Graphs can be used to model a wide varie
7 min read
Transpose graph Transpose of a directed graph G is another directed graph on the same set of vertices with all of the edges reversed compared to the orientation of the corresponding edges in G. That is, if G contains an edge (u, v) then the converse/transpose/reverse of G contains an edge (v, u) and vice versa. Giv
9 min read
Difference Between Graph and Tree Graphs and trees are two fundamental data structures used in computer science to represent relationships between objects. While they share some similarities, they also have distinct differences that make them suitable for different applications. Difference Between Graph and Tree What is Graph?A grap
2 min read
BFS and DFS on Graph
Breadth First Search or BFS for a GraphGiven a undirected graph represented by an adjacency list adj, where each adj[i] represents the list of vertices connected to vertex i. Perform a Breadth First Search (BFS) traversal starting from vertex 0, visiting vertices from left to right according to the adjacency list, and return a list conta
15+ min read
Depth First Search or DFS for a GraphIn Depth First Search (or DFS) for a graph, we traverse all adjacent vertices one by one. When we traverse an adjacent vertex, we completely finish the traversal of all vertices reachable through that adjacent vertex. This is similar to a tree, where we first completely traverse the left subtree and
13 min read
Applications, Advantages and Disadvantages of Depth First Search (DFS)Depth First Search is a widely used algorithm for traversing a graph. Here we have discussed some applications, advantages, and disadvantages of the algorithm. Applications of Depth First Search:1. Detecting cycle in a graph: A graph has a cycle if and only if we see a back edge during DFS. So we ca
4 min read
Applications, Advantages and Disadvantages of Breadth First Search (BFS)We have earlier discussed Breadth First Traversal Algorithm for Graphs. Here in this article, we will see the applications, advantages, and disadvantages of the Breadth First Search. Applications of Breadth First Search: 1. Shortest Path and Minimum Spanning Tree for unweighted graph: In an unweight
4 min read
Iterative Depth First Traversal of GraphGiven a directed Graph, the task is to perform Depth First Search of the given graph.Note: Start DFS from node 0, and traverse the nodes in the same order as adjacency list.Note : There can be multiple DFS traversals of a graph according to the order in which we pick adjacent vertices. Here we pick
10 min read
BFS for Disconnected GraphIn the previous post, BFS only with a particular vertex is performed i.e. it is assumed that all vertices are reachable from the starting vertex. But in the case of a disconnected graph or any vertex that is unreachable from all vertex, the previous implementation will not give the desired output, s
14 min read
Transitive Closure of a Graph using DFSGiven a directed graph, find out if a vertex v is reachable from another vertex u for all vertex pairs (u, v) in the given graph. Here reachable means that there is a path from vertex u to v. The reach-ability matrix is called transitive closure of a graph. For example, consider below graph: GraphTr
8 min read
Difference between BFS and DFSBreadth-First Search (BFS) and Depth-First Search (DFS) are two fundamental algorithms used for traversing or searching graphs and trees. This article covers the basic difference between Breadth-First Search and Depth-First Search.Difference between BFS and DFSParametersBFSDFSStands forBFS stands fo
2 min read
Cycle in a Graph
Detect Cycle in a Directed GraphGiven the number of vertices V and a list of directed edges, determine whether the graph contains a cycle or not.Examples: Input: V = 4, edges[][] = [[0, 1], [0, 2], [1, 2], [2, 0], [2, 3]]Cycle: 0 â 2 â 0 Output: trueExplanation: The diagram clearly shows a cycle 0 â 2 â 0 Input: V = 4, edges[][] =
15+ min read
Detect cycle in an undirected graphGiven an undirected graph, the task is to check if there is a cycle in the given graph.Examples:Input: V = 4, edges[][]= [[0, 1], [0, 2], [1, 2], [2, 3]]Undirected Graph with 4 vertices and 4 edgesOutput: trueExplanation: The diagram clearly shows a cycle 0 â 2 â 1 â 0Input: V = 4, edges[][] = [[0,
8 min read
Detect Cycle in a directed graph using colorsGiven a directed graph represented by the number of vertices V and a list of directed edges, determine whether the graph contains a cycle.Your task is to implement a function that accepts V (number of vertices) and edges (an array of directed edges where each edge is a pair [u, v]), and returns true
9 min read
Detect a negative cycle in a Graph | (Bellman Ford)Given a directed weighted graph, your task is to find whether the given graph contains any negative cycles that are reachable from the source vertex (e.g., node 0).Note: A negative-weight cycle is a cycle in a graph whose edges sum to a negative value.Example:Input: V = 4, edges[][] = [[0, 3, 6], [1
15+ min read
Cycles of length n in an undirected and connected graphGiven an undirected and connected graph and a number n, count the total number of simple cycles of length n in the graph. A simple cycle of length n is defined as a cycle that contains exactly n vertices and n edges. Note that for an undirected graph, each cycle should only be counted once, regardle
10 min read
Detecting negative cycle using Floyd WarshallWe are given a directed graph. We need compute whether the graph has negative cycle or not. A negative cycle is one in which the overall sum of the cycle comes negative. Negative weights are found in various applications of graphs. For example, instead of paying cost for a path, we may get some adva
12 min read
Clone a Directed Acyclic GraphA directed acyclic graph (DAG) is a graph which doesn't contain a cycle and has directed edges. We are given a DAG, we need to clone it, i.e., create another graph that has copy of its vertices and edges connecting them. Examples: Input : 0 - - - > 1 - - - -> 4 | / \ ^ | / \ | | / \ | | / \ |
12 min read