Shortest alternate colored path

Moderate
0/80
Average time to solve is 20m
profile
Contributed by
17 upvotes
Asked in companies
FlipkartGoogleHSBC

Problem statement

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 length of the shortest path 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’.

Example:
N = 4, redEdges = [[0, 1], [2, 3]], blueEdges = [[1, 2], [1, 3]]

example

The shortest paths for each node from node ‘0’ are:
1: 0->1         Length: 1
2: 0->1->2      Length: 2
3: 0->1->3      Length: 2
So, the ‘answer’ array will be: [0, 1, 2, 2].
Note:
1. The given graph could be a disconnected graph.

2. Any two nodes ‘i’ and ‘j’ can have at most one red edge from ‘i’ to ‘j’ and at most one blue edge from ‘i’ to ‘j’.
Detailed explanation ( Input/output format, Notes, Images )
Input format:
The first line of input contains an integer ‘T’ which denotes the number of test cases. Then, the ‘T’ test cases follow.

The first line of each test case contains three space-separated integers ‘N’, ‘rlen’, and ‘blen’ denoting the number of nodes in the graph, the size of array ‘redEdges’, and the size of array ‘blueEdges’.

The next 'rlen' lines of each test case contain two space-separated integers, ‘i’ and ‘j’ denoting a ‘red’ edge from node ‘i’ to node ‘j’.

The next 'blen' lines of each test case contain two space-separated integers, ‘i’ and ‘j’ denoting a ‘blue’ edge from node ‘i’ to node ‘j’.
Output format:
For every test case, print a single line containing N space-separated integers denoting array ‘answer’, where ‘answer[i]’ contains the valid shortest path length from node ‘0’ to node ‘i’. 

The output for each test case will be printed in a separate line.
Note:
You do not need to print anything; it has already been taken care of. Just implement the function.
Constraints:
1 <= T <= 100
1 <= N <= 200
0 <= rlen + blen <= 1000

Where ‘T’ is the number of test cases, ‘N’ is the number of nodes in the graph, ‘rlen’ is the size of array ‘redEdges’, and ‘blen’ is the size of array ‘blueEdges’.

Time limit: 1 second

Sample input 1:

2
4 2 2
0 1
1 3
1 1
1 2
4 2 2
0 1
1 3
0 2
2 3

Sample output 1:

0 1 2 3
0 1 1 -1

Explanation of sample input 1:

Test Case 1:

n = 4, redEdges = [[0,1], [1, 3]], blueEdges = [[1, 1], [1, 2]]

Sample1

The shortest paths for each node from node ‘0’ are:
1: 0->1          Length: 1
2: 0->1->2      Length: 2
3: 0->1->1->3   Length: 3
So, the ‘answer’ array will be: [0, 1, 2, 3].


Test Case 2:

n = 4, redEdges = [[0, 1], [1, 3]], blueEdges = [[0, 2], [2, 3]]

Sample2

The shortest paths for each node from node ‘0’ are:
1: 0->1     Length: 1
2: 0->2     Length: 1
3: No valid path available.
So, the ‘answer’ array will be: [0, 1, 1, -1].

Sample input 2:

2
3 1 1
2 1
1 0
3 1 2
1 0
0 1
0 2

Sample output 2:

0 -1 -1
0 1 1
Hint

Use a modified Dijkstra’s algorithm.

Approaches (2)
Modified Dijkstra’s algorithm

Dijkstra’s algorithm is used for finding the shortest path between nodes in a weighted graph. As the given graph is unweighted, the path length is equal to the number of edges, so consider each edge’s weight to be ‘1’. The maximum shortest path length will be ‘2*n - 3’, which will be achieved when all edges from node ‘i’ to ‘j’ (where ‘i != j’) have the same color ‘red’ and each node has a self-loop of ‘blue’ color or vice-versa.

 

For any node ‘x’ a valid path can be of two forms:

  • 0 -> ... -’blue edge’-> x. (Ending with blue edge)
  • 0 -> … -’red edge’-> x. (Ending with red edge)

 

Create two graphs ‘graph[2][n]’, the first ‘graph[0]’ containing red edges and the second ‘graph[1]’ containing blue edges. Here, ‘graph[i][j][k]’ means an edge of color type ‘i’ (‘0’ is red and ‘1’ is blue) from node ‘j’ to node ‘k’. A node can be represented in the form ‘[x, c]’ where ‘x’ is the node’s label and ‘c’ is the color of the incoming edge. Use a 2-d array ‘dist[n][2]’, where ‘dist[i][0]’ will store the length of the shortest path to reach node ‘i’ from a red edge and ‘dist[i][1]’ is the length with a blue edge. Use a 2-d array ‘sptSet[n][2]’ to check if we have found the shortest path for a node of form ‘[x, c]’.

 

Initialize the array ‘dist’ with value ‘2*n’ (i.e., unreachable from node ‘0’). Set ‘dist[0][0] = dist[0][1] = 0’ i.e., node ‘0’ is reachable from both blue and red edges with a path of zero length. Set ‘sptSet[0][0] = sptSet[0][1] = 0’, which means the length of shortest path to reach node ‘[0, 0]’ and ‘[0, 1]’ is zero.

 

Now, use Dijkstra’s shortest path algorithm to find the shortest path length for each such node ‘[x, c]’ from node ‘0’ (i.e., from ‘[0, 0]’ and ‘[0, 1]’). Let ‘minDist’ be the set of nodes (with their path length) that are reachable from the nodes in ‘sptSet’. Initially, both ‘sptSet’ and ‘minDist’ contain two nodes, ‘[0, 0]’ and ‘[0, 1]’, the source nodes.

 

According to Dijkstra’s algorithm: 

In each iteration, remove the node (let’s say ‘[x, c]’)  having the smallest path length in ‘minDist’ (let’s say ‘len’). Then ‘len’ is the shortest path length for node ‘[x, c]’ from node ‘0’. Set ‘sptSet[x][c] = true’ and ‘dist[x][c] = len’ as we have found it’s shortest path length. For all the nodes that are reachable from ‘[x, c]’, if they have ‘sptSet’ as false (i.e., their shortest path is not known) and their ‘dist’ value is larger than ‘dist[x][c] + 1’ then, add them to the set ‘minDist’ and update their ‘dist’ value. Stop the iteration when the set ‘minDist’ becomes empty, i.e., when we have found the shortest path for all nodes reachable from node ‘0’ (the source node).

 

Finally, for each node ‘i’ we have ‘answer[i] = min(dist[i][0], dist[i][1])’. If ‘answer[i]’ is still ‘2*n’ then no valid path exists to reach node ‘i’, set ‘answer[i] = -1’. Use a Priority Queue to implement ‘minDist’, so that we can extract the smallest element efficiently (in ‘O(log(n))’). Below is an implementation of Dijkstra’s algorithm using priority queue:

 

  • Create an array of list ‘graph[2][n]’ to store the given graph.
  • Run a loop where ‘i’ ranges from ‘0’ to ‘length(redEdges) - 1’:
    • ‘graph[0][redEdges[i][0]].append(redEdges[i][1])’
  • Run a loop where ‘i’ ranges from ‘0’ to ‘length(blueEdges) - 1’:
    • ‘graph[1][blueEdges[i][0]].append(blueEdges[i][1])’
  • Create a min priority queue ‘minDist’ that stores ‘Node’ objects and orders them by ‘Node->dist’. A ‘Node’ contains three values {‘dist’, ‘label’, ‘color’}.
  • Insert {0, 0, 0} and {0, 0, 1} in ‘minDist’. These are the source nodes, [0, 0] and [0, 1] with ‘dist’ equal to zero.
  • Initialize array ‘dist[n][2]’ with value ‘2*n’.
  • Set ‘dist[0][0] = dist[0][1] = 0’ (for source nodes).
  • Run a loop until ‘minDist’ is not empty:
    • ‘node = minDist.pop()’. Get the node with the smallest known distance and remove it from ‘minDist’.
    • ‘cur = node->label’. The current node label.
    • ‘c = node->color’. The color of the incoming edge.
    • If ‘dist[cur][c] < (node->dist)’ then, ignore this node as it doesn’t have the minimum distance:
      • Continue the loop.
    • Run a loop where ‘i’ ranges from ‘0’ to ‘length(graph[1 - c][cur]) - 1’
      • ‘next = graph[1 - c][cur][i]’. Move to the neighboring node through an edge of color ‘1 - c’, i.e., alternate of color ‘c’.
      • If  ‘dist[next][1 - c] > dist[next][c] + 1’, then:
        • ‘dist[next][1 - c] = dist[next][c] + 1’
        • ‘minDist.push({dist[next][1 - c], next, 1- c})’. Push an ‘Node’ object to ‘minDist’.
  • Create an array ‘answer[n]’ to store the answer.
  • Run a loop where ‘i’ ranges from ‘0’ to ‘n - 1’:
    • ‘answer[i] = min(dist[i][0], dist[i][1])’
    • If ‘answer[i] = 2*n’, then:
      • ‘answer[i] = -1’
  • Return the array ‘answer’ as the final answer.
Time Complexity

O(N + (RLEN + BLEN) * log(RLEN + BLEN)), where ‘RLEN’ is the number of red edges, ‘BLEN’ is the number of blue edges, and ‘N’ is the number of nodes.

 

Whenever a node’s distance is reduced, we add that instance of the node in the priority queue. Therefore, there can be multiple instances, but we only consider the instance with the minimum distance and ignore others. So, there can be at most ‘O(E)’ vertices (one for each edge) in the priority queue, hence the time complexity ‘O(E * log(E))’. Creating the ‘DIST’ to store the shortest path for each node array takes ‘O(N)’ time. As the number of edges in the graph ‘E = RLEN+ BLEN’, total time complexity is ‘O(N + (RLEN+ BLEN) * log(RLEN + BLEN))'.

Space Complexity

O(RLEN + BLEN + N), where 'RLEN' is the number of red edges, 'BLEN' is the number of blue edges, and ‘N’ is the number of nodes.

 

We create an adjacency list for the given graph, which takes ‘O(RLEN + BLEN)’ space. The array ‘DIST’ takes ‘O(N)’ space, and the priority queue stores ‘O(RLEN + BLEN)’ elements at most. Hence, the space complexity is ‘O(RLEN + BLEN + N)’.

Code Solution
(100% EXP penalty)
Shortest alternate colored path
Full screen
Console