Open In App

Shortest alternate colored path

Last Updated : 03 Jan, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

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], denoting an edge from node ‘i’ to node ‘j’ of the respective color. Your task is to compute an array ‘answer’ of size ‘N’, where ‘answer[i]’ stores the shortest path length from node ‘0’ to node ‘i’ such that the edges along the path have alternate colors. If there is no such path from node ‘0’ to ‘i’, then ‘answer[i] = -1’.

Examples:

Input: n = 3, redEdges = {{0, 0}}, blueEdges = {{0, 0}, {0, 1}}
Output: {0 1}
Explanation: For Node 0: The shortest path is to stay at Node 0 with a length of 0.
For Node 1: The shortest path is to move from Node 0 to Node 1 with a length of 1.
For Node 2: There is no direct edge to Node 2, so the path length is -1 (impossible).
Therefore, the ‘answer’ array is [0, 1] which represents the shortest alternate colored paths for each node and node 2 produces -1 so we will not consider it.

Input: n = 3, redEdges = {{1, 0}}, blueEdges = {{0, 1}, {0, 2}}
Output: {0 1 1}
Explanation: For Node 0: The shortest path is to stay at Node 0 with a length of 0.
For Node 1: The shortest path is to move from Node 0 to Node 1 with a length of 1.
For Node 2: The shortest path is to move from Node 0 to Node 2 with a length of 1.
The array is [0, 1, 1], representing the shortest alternate colored paths for each node in this graph.

Shortest alternate colored path using BFS:

The approach to find the Shortest alternate colored path by using Breadth-first search algorithm.

Steps were taken to solve the problem.

  • Two arrays of vectors, graph[2][n], represent the edges of red and blue colors. The first loop populates the red edges, and the second loop populates the blue edges.
  • A 2D vector, distances, is created to store the shortest distances for each node (indexed by node and color). All distances are initialized to 2 * n, and the source node is set to have a distance of 0 for both colors.
  • A queue, bfsQueue, is used for BFS traversal. It starts with the source node for both red and blue colors.
  • The BFS loop processes nodes from the queue, exploring neighbors with alternate colors. For each neighbor, it checks if the distance from the source node of the opposite color can be reduced. If so, it updates the distance and adds the neighbor to the queue with the alternate color.
  • Finally, the code computes the result array. For each node, it calculates the minimum distance between the red and blue colors and sets it as the result. If a node’s distance is still 2 * n, it means there’s no valid path, so it’s set to -1.

Below is the C++ implementation of the above approach:

C++




#include <bits/stdc++.h>
using namespace std;
 
vector<int> shortestAlternateColoredPath(
    int n, vector<vector<int> >& redEdges,
    vector<vector<int> >& blueEdges)
{
    // Create a graph to store red and blue edges for each
    // node.
    vector<int> graph[2][n];
 
    // Populate the red edges in the graph.
    for (int i = 0; i < redEdges.size(); i++) {
        graph[0][redEdges[i][0]].push_back(redEdges[i][1]);
    }
 
    // Populate the blue edges in the graph.
    for (int i = 0; i < blueEdges.size(); i++) {
        graph[1][blueEdges[i][0]].push_back(
            blueEdges[i][1]);
    }
 
    // Create a 2D vector to store distances for each node
    // and color.
    vector<vector<int> > distances(n,
                                   vector<int>(2, 2 * n));
 
    // Initialize distances for the source node (Node 0)
    // with both red and blue colors to 0.
    distances[0][0] = distances[0][1] = 0;
 
    // Create a queue for Breadth-First Search traversal.
    queue<pair<int, int> > bfsQueue;
 
    // Start the BFS traversal from the source node with
    // both red and blue colors.
    bfsQueue.push(make_pair(0, 0));
    bfsQueue.push(make_pair(0, 1));
 
    // Perform BFS to find the shortest alternate colored
    // paths.
    while (!bfsQueue.empty()) {
        int current = bfsQueue.front().first;
        int color = bfsQueue.front().second;
        bfsQueue.pop();
 
        // Explore neighbors with the opposite color.
        for (int i = 0;
             i < graph[1 - color][current].size(); i++) {
            int next = graph[1 - color][current][i];
 
            // Update distances if a shorter path is found.
            if (distances[next][1 - color]
                > distances[current][color] + 1) {
                distances[next][1 - color]
                    = distances[current][color] + 1;
                bfsQueue.push(make_pair(next, 1 - color));
            }
        }
    }
 
    // Calculate the final result array.
    vector<int> result(n);
    for (int i = 0; i < n; i++) {
        result[i] = min(distances[i][0], distances[i][1]);
 
        // If there is no valid path, set the distance to
        // -1.
        if (result[i] == 2 * n)
            result[i] = -1;
    }
 
    return result;
}
 
// Driver Code
int main()
{
    int n = 3;
    vector<vector<int> > redEdges = { { 1, 0 } };
    vector<vector<int> > blueEdges = { { 0, 1 }, { 0, 2 } };
 
    vector<int> result = shortestAlternateColoredPath(
        n, redEdges, blueEdges);
 
    cout << "Shortest Alternate Colored Path for each node:"
         << endl;
    for (int i = 0; i < n; i++) {
        cout << result[i] << " ";
    }
 
    return 0;
}


Java




// Java program to implement the above approach
 
import java.util.*;
 
public class GFG {
    public static List<Integer>
    shortestAlternateColoredPath(
        int n, List<List<Integer> > redEdges,
        List<List<Integer> > blueEdges)
    {
 
        // Create a graph to store red and blue edges for
        // each node.
        List<List<Integer> >[] graph = new ArrayList[2];
        for (int i = 0; i < 2; i++) {
            graph[i] = new ArrayList<>();
            for (int j = 0; j < n; j++) {
                graph[i].add(new ArrayList<>());
            }
        }
 
        // Populate the red edges in the graph.
        for (List<Integer> redEdge : redEdges) {
            graph[0]
                .get(redEdge.get(0))
                .add(redEdge.get(1));
        }
 
        // Populate the blue edges in the graph.
        for (List<Integer> blueEdge : blueEdges) {
            graph[1]
                .get(blueEdge.get(0))
                .add(blueEdge.get(1));
        }
 
        // Create a 2D array to store distances for each
        // node and color.
        int[][] distances = new int[n][2];
        for (int[] distance : distances) {
            Arrays.fill(distance, 2 * n);
        }
 
        // Initialize distances for the source node (Node 0)
        // with both red and blue colors to 0.
        distances[0][0] = distances[0][1] = 0;
 
        // Create a queue for Breadth-First Search
        // traversal.
        Queue<int[]> bfsQueue = new LinkedList<>();
 
        // Start the BFS traversal from the source node with
        // both red and blue colors.
        bfsQueue.offer(new int[] { 0, 0 });
        bfsQueue.offer(new int[] { 0, 1 });
 
        // Perform BFS to find the shortest alternate
        // colored paths.
        while (!bfsQueue.isEmpty()) {
            int[] current = bfsQueue.poll();
            int currentNode = current[0];
            int color = current[1];
 
            // Explore neighbors with the opposite color.
            for (int next :
                 graph[1 - color].get(currentNode)) {
                // Update distances if a shorter path is
                // found.
                if (distances[next][1 - color]
                    > distances[currentNode][color] + 1) {
                    distances[next][1 - color]
                        = distances[currentNode][color] + 1;
                    bfsQueue.offer(
                        new int[] { next, 1 - color });
                }
            }
        }
 
        // Calculate the final result list.
        List<Integer> result = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            result.add(
                Math.min(distances[i][0], distances[i][1]));
 
            // If there is no valid path, set the distance
            // to -1.
            if (result.get(i) == 2 * n)
                result.set(i, -1);
        }
 
        return result;
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        int n = 3;
        List<List<Integer> > redEdges
            = Arrays.asList(Arrays.asList(1, 0));
        List<List<Integer> > blueEdges = Arrays.asList(
            Arrays.asList(0, 1), Arrays.asList(0, 2));
 
        List<Integer> result = shortestAlternateColoredPath(
            n, redEdges, blueEdges);
 
        System.out.println(
            "Shortest Alternate Colored Path for each node:");
        for (int value : result) {
            System.out.print(value + " ");
        }
    }
}
 
// This code is contributed by Abhinav Mahajan (abhinav_m22)


Python3




from collections import deque
 
 
def shortest_alternate_colored_path(n, red_edges, blue_edges):
    # Create a graph to store red and blue edges for each node.
    graph = [[[] for j in range(n)] for i in range(2)]
 
    # Populate the red edges in the graph.
    for i in range(len(red_edges)):
        graph[0][red_edges[i][0]].append(red_edges[i][1])
 
    # Populate the blue edges in the graph.
    for i in range(len(blue_edges)):
        graph[1][blue_edges[i][0]].append(blue_edges[i][1])
 
    # Create a 2D vector to store distances
    # for each node and color.
    distances = [[2 * n] * 2 for _ in range(n)]
 
    # Initialize distances for the source node (Node 0)
    # with both red and blue colors to 0.
    distances[0][0] = distances[0][1] = 0
 
    # Create a queue for Breadth-First Search traversal.
    bfs_queue = deque([(0, 0), (0, 1)])
 
    # Start the BFS traversal from the source nod
    # with both red and blue colors.
    while bfs_queue:
        current, color = bfs_queue.popleft()
 
        # Explore neighbors with the opposite color.
        for i in range(len(graph[1 - color][current])):
            next_node = graph[1 - color][current][i]
 
            # Update distances if a shorter path is found.
            if distances[next_node][1 - color] > distances[current][color] + 1:
                distances[next_node][1 - color] = distances[current][color] + 1
                bfs_queue.append((next_node, 1 - color))
 
    # Calculate the final result array.
    result = [min(distances[i][0], distances[i][1]) if min(
        distances[i]) != 2 * n else -1 for i in range(n)]
    return result
 
 
# Driver Code
if __name__ == "__main__":
    n = 3
    red_edges = [[1, 0]]
    blue_edges = [[0, 1], [0, 2]]
 
    result = shortest_alternate_colored_path(n, red_edges, blue_edges)
 
    print("Shortest Alternate Colored Path for each node:")
    for i in range(n):
        print(result[i], end=" ")
 
# This code is contributed by ragul21


C#




// C# program for the above approach
using System;
using System.Collections.Generic;
 
public class GFG {
    public static List<int>
    ShortestAlternateColoredPath(int n,
                                 List<List<int> > redEdges,
                                 List<List<int> > blueEdges)
    {
        // Create a graph to store red and blue edges for
        // each node.
        List<int>[] graph = new List<int>[ 2 * n ];
        for (int i = 0; i < 2 * n; i++) {
            graph[i] = new List<int>();
        }
 
        // Populate the red edges in the graph.
        foreach(var edge in redEdges)
        {
            graph[edge[0]].Add(edge[1]);
        }
 
        // Populate the blue edges in the graph.
        foreach(var edge in blueEdges)
        {
            graph[edge[0] + n].Add(edge[1] + n);
        }
 
        // Create a 2D array to store distances for each
        // node and color.
        int[, ] distances = new int[n, 2];
        for (int i = 0; i < n; i++) {
            distances[i, 0] = distances[i, 1] = 2 * n;
        }
 
        // Initialize distances for the source node (Node 0)
        // with both red and blue colors to 0.
        distances[0, 0] = distances[0, 1] = 0;
 
        // Create a queue for Breadth-First Search
        // traversal.
        Queue<Tuple<int, int> > bfsQueue
            = new Queue<Tuple<int, int> >();
 
        // Start the BFS traversal from the source node with
        // both red and blue colors.
        bfsQueue.Enqueue(new Tuple<int, int>(0, 0));
        bfsQueue.Enqueue(new Tuple<int, int>(0, 1));
 
        // Perform BFS to find the shortest alternate
        // colored paths.
        while (bfsQueue.Count > 0) {
            var current = bfsQueue.Dequeue();
            int currentNode = current.Item1;
            int color = current.Item2;
 
            // Explore neighbors with the opposite color.
            foreach(
                var next in
                    graph[n * (1 - color) + currentNode])
            {
                // Update distances if a shorter path is
                // found.
                if (distances[next % n, 1 - color]
                    > distances[currentNode, color] + 1) {
                    distances[next % n, 1 - color]
                        = distances[currentNode, color] + 1;
                    bfsQueue.Enqueue(new Tuple<int, int>(
                        next % n, 1 - color));
                }
            }
        }
 
        // Calculate the final result array.
        List<int> result = new List<int>();
        for (int i = 0; i < n; i++) {
            result.Add(
                Math.Min(distances[i, 0], distances[i, 1]));
 
            // If there is no valid path, set the distance
            // to -1.
            if (result[i] == 2 * n)
                result[i] = -1;
        }
 
        return result;
    }
 
    public static void Main(string[] args)
    {
        int n = 3;
        List<List<int> > redEdges
            = new List<List<int> >{ new List<int>{ 1, 0 } };
        List<List<int> > blueEdges
            = new List<List<int> >{ new List<int>{ 0, 1 },
                                    new List<int>{ 0, 2 } };
 
        List<int> result = ShortestAlternateColoredPath(
            n, redEdges, blueEdges);
 
        Console.WriteLine(
            "Shortest Alternate Colored Path for each node:");
        foreach(var item in result)
        {
            Console.Write(item + " ");
        }
 
        Console.WriteLine();
    }
}
 
// This code is contributed by Susobhan Akhuli


Javascript




class GFG {
    static shortestAlternateColoredPath(n, redEdges, blueEdges) {
        // Create a graph to store red and blue edges for each node.
        const graph = [[], []];
        for (let i = 0; i < n; i++) {
            graph[0].push([]);
            graph[1].push([]);
        }
 
        // Populate the red edges in the graph.
        for (const redEdge of redEdges) {
            graph[0][redEdge[0]].push(redEdge[1]);
        }
 
        // Populate the blue edges in the graph.
        for (const blueEdge of blueEdges) {
            graph[1][blueEdge[0]].push(blueEdge[1]);
        }
 
        // Create a 2D array to store distances for each node and color.
        const distances = Array.from({ length: n }, () => Array(2).fill(2 * n));
 
        // Initialize distances for the source node (Node 0) with both red and blue colors to 0.
        distances[0][0] = distances[0][1] = 0;
 
        // Create a queue for Breadth-First Search traversal.
        const bfsQueue = [];
 
        // Start the BFS traversal from the source node with both red and blue colors.
        bfsQueue.push([0, 0]);
        bfsQueue.push([0, 1]);
 
        // Perform BFS to find the shortest alternate colored paths.
        while (bfsQueue.length > 0) {
            const current = bfsQueue.shift();
            const currentNode = current[0];
            const color = current[1];
 
            // Explore neighbors with the opposite color.
            for (const next of graph[1 - color][currentNode]) {
                // Update distances if a shorter path is found.
                if (distances[next][1 - color] > distances[currentNode][color] + 1) {
                    distances[next][1 - color] = distances[currentNode][color] + 1;
                    bfsQueue.push([next, 1 - color]);
                }
            }
        }
 
        // Calculate the final result list.
        const result = [];
        for (let i = 0; i < n; i++) {
            result.push(Math.min(distances[i][0], distances[i][1]));
 
            // If there is no valid path, set the distance to -1.
            if (result[i] === 2 * n) {
                result[i] = -1;
            }
        }
 
        return result;
    }
 
    // Driver Code
    static main() {
        const n = 3;
        const redEdges = [[1, 0]];
        const blueEdges = [[0, 1], [0, 2]];
 
        const result = this.shortestAlternateColoredPath(n, redEdges, blueEdges);
 
        console.log("Shortest Alternate Colored Path for each node:");
        console.log(result.join(" "));
    }
}
 
// Run the main function
GFG.main();
 
 
// This code is contrubuted by akshitaguprzj3


Output

Shortest Alternate Colored Path for each node:
0 1 1 








Time Complexity: O(N + RLEN + BLEN), where ‘RLEN’ is the number of red edges, and ‘BLEN’ is the number of blue edges, and ‘N’ is the number of nodes.
Auxiliary space: O(N + RLEN + BLEN), where ‘RLEN’ is the number of red edges, and ‘BLEN’ is the number of blue edges, and ‘N’ is the number of nodes.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads