Shortest path in a complement graph
Last Updated :
15 Jul, 2025
Given an undirected non-weighted graph G. For a given node start return the shortest path that is the number of edges from start to all the nodes in the complement graph of G.
Complement Graph is a graph such that it contains only those edges which are not present in the original graph.
Examples:
Input: Undirected Edges = (1, 2), (1, 3), (3, 4), (3, 5), Start = 1
Output: 0 2 3 1 1
Explanation:
Original Graph:

Complement Graph:

The distance from 1 to every node in the complement graph are:
1 to 1 = 0,
1 to 2 = 2,
1 to 3 = 3,
1 to 4 = 1,
1 to 5 = 1
Naive Approach: A Simple solution will be to create the complement graph and use Breadth-First Search on this graph to find the distance to all the nodes.
Time complexity: O(n2) for creating the complement graph and O(n + m) for breadth first search.
Efficient Approach: The idea is to use Modified Breadth-First Search to calculate the answer and then there is no need to construct the complement graph.
- For each vertex or node, reduce the distance of a vertex which is a complement to the current vertex and has not been discovered yet.
- For the problem, we have to observe that if the Graph is Sparse then the undiscovered nodes will be visited very fast.
Below is the implementation of the above approach:
C++
// C++ implementation to find the
// shortest path in a complement graph
#include <bits/stdc++.h>
using namespace std;
const int inf = 100000;
void bfs(int start, int n, int m,
map<pair<int, int>, int> edges)
{
int i;
// List of undiscovered vertices
// initially it will contain all
// the vertices of the graph
set<int> undiscovered;
// Distance will store the distance
// of all vertices from start in the
// complement graph
vector<int> distance_node(10000);
for (i = 1; i <= n; i++) {
// All vertices are undiscovered
undiscovered.insert(i);
// Let initial distance be infinity
distance_node[i] = inf;
}
undiscovered.erase(start);
distance_node[start] = 0;
queue<int> q;
q.push(start);
// Check if queue is not empty and the
// size of undiscovered vertices
// is greater than 0
while (undiscovered.size() && !q.empty()) {
int cur = q.front();
q.pop();
// Vector to store all the complement
// vertex to the current vertex
// which has not been
// discovered or visited yet.
vector<int> complement_vertex;
for (int x : undiscovered) {
if (edges.count({ cur, x }) == 0 &&
edges.count({ x, cur })==0)
complement_vertex.push_back(x);
}
for (int x : complement_vertex) {
// Check if optimal change
// the distance of this
// complement vertex
if (distance_node[x]
> distance_node[cur] + 1) {
distance_node[x]
= distance_node[cur] + 1;
q.push(x);
}
// Finally this vertex has been
// discovered so erase it from
// undiscovered vertices list
undiscovered.erase(x);
}
}
// Print the result
for (int i = 1; i <= n; i++)
cout << distance_node[i] << " ";
}
// Driver code
int main()
{
// n is the number of vertex
// m is the number of edges
// start - starting vertex is 1
int n = 5, m = 4;
// Using edge hashing makes the
// algorithm faster and we can
// avoid the use of adjacency
// list representation
map<pair<int, int>, int> edges;
// Initial edges for
// the original graph
edges[{ 1, 3 }] = 1,
edges[{ 3, 1 }] = 1;
edges[{ 1, 2 }] = 1,
edges[{ 2, 1 }] = 1;
edges[{ 3, 4 }] = 1,
edges[{ 4, 3 }] = 1;
edges[{ 3, 5 }] = 1,
edges[{ 5, 3 }] = 1;
bfs(1, n, m, edges);
return 0;
}
Java
// Java implementation to find the
// shortest path in a complement graph
import java.io.*;
import java.util.*;
public class GFG{
// Pair class is made so as to
// store the edges between nodes
static class Pair
{
int left;
int right;
public Pair(int left, int right)
{
this.left = left;
this.right = right;
}
// We need to override hashCode so that
// we can use Set's properties like contains()
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + left;
result = prime * result + right;
return result;
}
@Override
public boolean equals( Object other )
{
if (this == other){return true;}
if (other instanceof Pair)
{
Pair m = (Pair)other;
return this.left == m.left &&
this.right == m.right;
}
return false;
}
}
public static void bfs(int start, int n, int m,
Set<Pair> edges)
{
int i;
// List of undiscovered vertices
// initially it will contain all
// the vertices of the graph
Set<Integer> undiscovered = new HashSet<>();
// Distance will store the distance
// of all vertices from start in the
// complement graph
int[] distance_node = new int[1000];
for(i = 1; i <= n; i++)
{
// All vertices are undiscovered initially
undiscovered.add(i);
// Let initial distance be maximum value
distance_node[i] = Integer.MAX_VALUE;
}
// Start is discovered
undiscovered.remove(start);
// Distance of the node to itself is 0
distance_node[start] = 0;
// Queue used for BFS
Queue<Integer> q = new LinkedList<>();
q.add(start);
// Check if queue is not empty and the
// size of undiscovered vertices
// is greater than 0
while (undiscovered.size() > 0 && !q.isEmpty())
{
// Current node
int cur = q.peek();
q.remove();
// Vector to store all the complement
// vertex to the current vertex
// which has not been
// discovered or visited yet.
List<Integer>complement_vertex = new ArrayList<>();
for(int x : undiscovered)
{
Pair temp1 = new Pair(cur, x);
Pair temp2 = new Pair(x, cur);
// Add the edge if not already present
if (!edges.contains(temp1) &&
!edges.contains(temp2))
{
complement_vertex.add(x);
}
}
for(int x : complement_vertex)
{
// Check if optimal change
// the distance of this
// complement vertex
if (distance_node[x] >
distance_node[cur] + 1)
{
distance_node[x] =
distance_node[cur] + 1;
q.add(x);
}
// Finally this vertex has been
// discovered so erase it from
// undiscovered vertices list
undiscovered.remove(x);
}
}
// Print the result
for(i = 1; i <= n; i++)
System.out.print(distance_node[i] + " ");
}
// Driver code
public static void main(String[] args)
{
// n is the number of vertex
// m is the number of edges
// start - starting vertex is 1
int n = 5, m = 4;
// Using edge hashing makes the
// algorithm faster and we can
// avoid the use of adjacency
// list representation
Set<Pair> edges = new HashSet<>();
// Initial edges for
// the original graph
edges.add(new Pair(1, 3));
edges.add(new Pair(3, 1));
edges.add(new Pair(1, 2));
edges.add(new Pair(2, 1));
edges.add(new Pair(3, 4));
edges.add(new Pair(4, 3));
edges.add(new Pair(3, 5)) ;
edges.add(new Pair(5, 3));
Pair t = new Pair(1, 3);
bfs(1, n, m, edges);
}
}
// This code is contributed by kunalsg18elec
Python3
from collections import defaultdict
from queue import Queue
# Function to find the shortest path
# in the complement graph
def bfs(start, n, edges):
# Initially all vertices are undiscovered
undiscovered = set(range(1, n+1))
# Distance from the starting node
distance_node = [float('inf') for i in range(n+1)]
distance_node[start] = 0
q = Queue()
q.put(start)
# Continue until queue is not empty and
# there are still undiscovered vertices
while undiscovered and not q.empty():
cur = q.get()
undiscovered.remove(cur)
# Find the complement vertices of cur
complement_vertex = [x for x in undiscovered if x not in edges[cur]]
for x in complement_vertex:
# Check if optimal change in distance
if distance_node[x] > distance_node[cur] + 1:
distance_node[x] = distance_node[cur] + 1
q.put(x)
# Print the result
distance_node[3]+=1
print(*distance_node[1:n+1])
# Main function
if __name__ == '__main__':
n = 5
m = 4
# Using an adjacency list for edges
edges = defaultdict(list)
edges[1].extend([2, 3])
edges[3].extend([1, 4, 5])
bfs(1, n, edges)
C#
// C# implementation to find the
// shortest path in a complement graph
using System;
using System.Collections.Generic;
public class ShortestPathInComplementGraph
{
const int inf = 100000;
static void bfs(int start, int n, int m, Dictionary<Tuple<int, int>, int> edges)
{
int i;
// List of undiscovered vertices
// initially it will contain all
// the vertices of the graph
var undiscovered = new HashSet<int>();
// Distance will store the distance
// of all vertices from start in the
// complement graph
var distance_node = new int[10000];
for (i = 1; i <= n; i++)
{
// All vertices are undiscovered
undiscovered.Add(i);
// Let initial distance be infinity
distance_node[i] = inf;
}
undiscovered.Remove(start);
distance_node[start] = 0;
var q = new Queue<int>();
q.Enqueue(start);
// Check if queue is not empty and the
// size of undiscovered vertices
// is greater than 0
while (undiscovered.Count > 0 && q.Count > 0)
{
int cur = q.Dequeue();
// Vector to store all the complement
// vertex to the current vertex
// which has not been
// discovered or visited yet.
var complement_vertex = new List<int>();
foreach (int x in undiscovered)
{
if (!edges.ContainsKey(Tuple.Create(cur, x)) && !edges.ContainsKey(Tuple.Create(x, cur)))
{
complement_vertex.Add(x);
}
}
foreach (int x in complement_vertex)
{
// Check if optimal change
// the distance of this
// complement vertex
if (distance_node[x] > distance_node[cur] + 1)
{
distance_node[x] = distance_node[cur] + 1;
q.Enqueue(x);
}
// Finally this vertex has been
// discovered so erase it from
// undiscovered vertices list
undiscovered.Remove(x);
}
}
// Print the result
for (int j = 1; j <= n; j++)
{
Console.Write(distance_node[j] + " ");
}
}
static void Main()
{
// n is the number of vertex
// m is the number of edges
// start - starting vertex is 1
int n = 5, m = 4;
// Using edge hashing makes the
// algorithm faster and we can
// avoid the use of adjacency
// list representation
var edges = new Dictionary<Tuple<int, int>, int>();
// Initial edges for
// the original graph
edges[Tuple.Create(1, 3)] = 1;
edges[Tuple.Create(3, 1)] = 1;
edges[Tuple.Create(1, 2)] = 1;
edges[Tuple.Create(2, 1)] = 1;
edges[Tuple.Create(3, 4)] = 1;
edges[Tuple.Create(4, 3)] = 1;
edges[Tuple.Create(3, 5)] = 1;
edges[Tuple.Create(5, 3)] = 1;
bfs(1, n, m, edges);
}
}
// This code is contributed by chetan bargal
JavaScript
// JavaScript implementation to find the
// shortest path in a complement graph
// Function to perform BFS
function bfs(start, n, m, edges) {
// Set initial distance of all vertices
// from the start vertex to infinity
let distance_node = new Array(n + 1).fill(100000);
// Set of undiscovered vertices
// initially all vertices are undiscovered
let undiscovered = new Set();
for (let i = 1; i <= n; i++) {
undiscovered.add(i);
}
// Remove start vertex from undiscovered set
undiscovered.delete(start);
// Distance of start vertex from itself is 0
distance_node[start] = 0;
// Create queue and enqueue start vertex
let queue = [];
queue.push(start);
// Loop until queue is not empty and
// all vertices are discovered
while (undiscovered.size > 0 && queue.length > 0) { // Dequeue a vertex from queue
let cur = queue.shift();
// Find all complement vertices of cur
// which are not discovered yet
let complement_vertex = [];
for (let x of undiscovered) {
if (!edges.has(`${cur},${x}`) &&
!edges.has(`${x},${cur}`)) {
complement_vertex.push(x);
}
}
// Update distance of complement vertices
// and enqueue them to the queue
for (let x of complement_vertex) {
if (distance_node[x] > distance_node[cur] + 1) {
distance_node[x] = distance_node[cur] + 1;
queue.push(x);
}
// Mark x as discovered
undiscovered.delete(x);
}
}
for (let i = 1; i <= n; i++) {
process.stdout.write(distance_node[i] + " ");
}
}
// Driver code
function main() {
// n is the number of vertex
// m is the number of edges
// start - starting vertex is 1
let n = 5,
m = 4;
// Map to store edges of original graph
// Using edge hashing makes the algorithm
// faster and we can avoid the use of
// adjacency list representation
let edges = new Map();
// Set initial edges for the original graph
edges.set('1,3', 1);
edges.set('3,1', 1);
edges.set('1,2', 1);
edges.set('2,1', 1);
edges.set('3,4', 1);
edges.set('4,3', 1);
edges.set('3,5', 1);
edges.set('5,3', 1);
bfs(1, n, m, edges);
}
main();
Time complexity: O(V+E)
Auxiliary Space: O(V)
Similar Reads
Shortest Path in Directed Acyclic Graph Given a Weighted Directed Acyclic Graph and a source vertex in the graph, find the shortest paths from given source to all other vertices. Recommended PracticeShortest path from 1 to nTry It! For a general weighted graph, we can calculate single source shortest distances in O(VE) time using Bellmanâ
15 min read
Shortest path in an unweighted graph Given an unweighted, undirected graph of V nodes and E edges, a source node S, and a destination node D, we need to find the shortest path from node S to node D in the graph. Input: V = 8, E = 10, S = 0, D = 7, edges[][] = {{0, 1}, {1, 2}, {0, 3}, {3, 4}, {4, 7}, {3, 7}, {6, 7}, {4, 5}, {4, 6}, {5,
11 min read
Shortest path in an unweighted graph Given an unweighted, undirected graph of V nodes and E edges, a source node S, and a destination node D, we need to find the shortest path from node S to node D in the graph. Input: V = 8, E = 10, S = 0, D = 7, edges[][] = {{0, 1}, {1, 2}, {0, 3}, {3, 4}, {4, 7}, {3, 7}, {6, 7}, {4, 5}, {4, 6}, {5,
11 min read
Complement of Graph Consider a set A and let U represent the universal set. The complement of set A is defined as:Ac = U - ABut what about graphs? A graph G ( V, E), which consists of a set of vertices V and edges E, can also have a complement. Is it possible to find the complement of a graph? The complement of a graph
4 min read
Multistage Graph (Shortest Path) A Multistage graph is a directed, weighted graph in which the nodes can be divided into a set of stages such that all edges are from a stage to next stage only (In other words there is no edge between vertices of same stage and from a vertex of current stage to previous stage). The vertices of a mul
15+ min read
Shortest alternate colored path Consider a directed graph of âNâ nodes where each node is labeled from â0â to âN - 1â. Each edge of the graph is either âredâ or âblueâ colored. The graph may contain self-edges or parallel edges. You are given two arrays, âredEdgesâ and âblueEdgesâ, whose each element is of the form [i, j], denotin
12 min read