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 codeint 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 nodesstatic 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 defaultdictfrom queue import QueueÂ
# Function to find the shortest path# in the complement graphdef 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 functionif __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 graphusing 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 BFSfunction 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 codefunction 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(); |
0 2 3 1 1
Time complexity: O(V+E)Â
Auxiliary Space: O(V)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!


… [Trackback]
[…] Info to that Topic: geeksforgeeks.org/shortest-path-in-a-complement-graph/ […]
… [Trackback]
[…] Read More Information here to that Topic: geeksforgeeks.org/shortest-path-in-a-complement-graph/ […]