Open In App

Shortest Path with even number of Edges from Source to Destination

Last Updated : 23 Feb, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given an undirected graph G, the task is to find the shortest path of even-length, given 1 as Source Node and N as Destination Node. Path length refers to the number of edges present in a path (not the cost of the path).

Examples: 

Input: N = 5, G is given below: 
 

Input Graph

Output: 10 
Explanation: 
All paths from 1(source node) to 5 (destination node) are: 
1->2->5 
Cost: 16 Length: 2(even) 
1->2->3->5 
Cost: 4 Length: 3(odd) 
1->2->3->4->5 
Cost: 10 Length: 4(even) 
The shortest path is 1->2->3->5 with total cost 4, but it has an odd-length path and since we are interested in even-length paths only, the shortest path with even-length is 1->2->3->4->5, with total cost 10.

Input 2: N = 4, G is given below: 
 

Input Graph

Output: -1
Explanation: 
There is no path of even-length from 1(source node) to 4(destination node). 

Approach: 
Create a new Graph (G’). For each node V in initial graph G, create two new nodes V_even and V_odd

Here, V_odd will be represented as ((V * 10) + 1) and V_even as ((V * 10) + 2). 
For example, if node V = 4 then V_odd = 41 and V_even = 42. 
 

Now, for each edge (U, V) in G, add two new edges in G’, (U_even, V_odd) and (U_odd, V_even). Finally, find the Shortest path from (source_even) node to (destination_even) node using Dijkstra Shortest Path Algorithm.
For Graph given in Input 1(above), G’ can be represented as: 
 

Graph G'

It can observed from the graph G’ that there are only even length paths from (1_even) to (5_even). Thus, the odd-length paths get separated in G’ and the required shortest path can be obtained.

Below is the implementation of the above approach: 

C++




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
const int MAXX = 10000, INF = 1e9;
 
// Adjacency List: to represent graph
vector<vector<pair<int, int> > >
    adj(MAXX * 10 + 3);
 
// Distance Array: to store shortest
// distance to every node
vector<int> dist(MAXX * 10 + 3, INF);
 
// returns value which will
// represent even_x
int even(int x)
{
    return x * 10 + 2;
}
// returns value which will
// represent odd_x
int odd(int x)
{
    return x * 10 + 1;
}
 
// converting edge (a->b) to 2
// different edges i.e. (a->b)
// converts to (1). even_a -> odd_b
// (2). odd_a -> even_b
// since, graph is undirected, so we
// push them in reverse order too
// hence, 4 push_back operations are
// there.
void addEdge(int a, int b, int cost)
{
    adj[even(a)].push_back(
        { odd(b), cost });
    adj[odd(a)].push_back(
        { even(b), cost });
    adj[odd(b)].push_back(
        { even(a), cost });
    adj[even(b)].push_back(
        { odd(a), cost });
}
 
// Function calculates shortest
// distance to all nodes from
// "source" using Dijkstra
// Shortest Path Algorithm
// and returns shortest distance
// to "destination"
int dijkstra(int source,
             int destination)
{
 
    /* Priority Queue/min-heap
    to store and process
    (distance, node) */
    priority_queue<pair<int, int>,
                   vector<pair<int, int> >,
                   greater<pair<int, int> > >
        pq;
 
    // pushing source node to
    // priority queue and dist from
    // source to source is set to 0
    pq.push({ 0, even(source) });
    dist[even(source)] = 0;
 
    while (!pq.empty()) {
 
        // U is the node at top
        // of the priority queue
        // note that pq.top().first
        // refers to the Distance
        // and pq.top().second
        // will refer to the Node
        int u = pq.top().second;
        pq.pop();
 
        // exploring all neighbours
        // of node u
        for (pair<int, int> p :
             adj[u]) {
 
            /* v is neighbour node of u
          and c is the cost/weight
          of edge (u, v) */
            int v = p.first;
            int c = p.second;
 
            // relaxation: checking if there
            // is a shorter path to v via u
            if (dist[u] + c
                < dist[v]) {
 
                // updating distance of v
                dist[v] = dist[u] + c;
                pq.push({ dist[v], v });
            }
        }
    }
 
    // returning shortest
    // distance to "destination"
    return dist[even(destination)];
}
 
// Driver function
int main()
{
    // n = number of Nodes,
    // m = number of Edges
    int n = 5, m = 6;
    addEdge(1, 2, 1);
    addEdge(2, 3, 2);
    addEdge(2, 5, 15);
    addEdge(3, 5, 1);
    addEdge(3, 4, 4);
    addEdge(5, 4, 3);
 
    int source = 1;
    int destination = n;
    int ans = dijkstra(source, destination);
 
    // if ans is INF: There is no
    // even length path from source
    // to destination else path
    // exists and we print the
    // shortest distance
    if (ans == INF)
        cout << "-1"
             << "\n";
    else
        cout << ans << "\n";
 
    return 0;
}


Java




// Java program for the above approach
import java.util.ArrayList;
import java.util.Arrays;
import java.util.PriorityQueue;
 
class GFG{
 
static class Pair implements Comparable<Pair>
{
    int first, second;
 
    public Pair(int first, int second)
    {
        this.first = first;
        this.second = second;
    }
 
    @Override
    public int compareTo(GFG.Pair o)
    {
        if (this.first == o.first)
        {
            return this.second - o.second;
        }
        return this.first - o.first;
    }
}
 
static final int MAXX = 10000, INF = (int)1e9;
 
// Adjacency List: to represent graph
@SuppressWarnings("unchecked")
static ArrayList<Pair>[] adj = new ArrayList[MAXX * 10 + 3];
 
// Distance Array: to store shortest
// distance to every node
static int[] dist = new int[MAXX * 10 + 3];
 
// Returns value which will
// represent even_x
static int even(int x)
{
    return x * 10 + 2;
}
 
// Returns value which will
// represent odd_x
static int odd(int x)
{
    return x * 10 + 1;
}
 
// Converting edge (a->b) to 2
// different edges i.e. (a->b)
// converts to (1). even_a -> odd_b
// (2). odd_a -> even_b
// since, graph is undirected, so we
// push them in reverse order too
// hence, 4 push_back operations are
// there.
static void addEdge(int a, int b, int cost)
{
    adj[even(a)].add(new Pair(odd(b), cost));
    adj[odd(a)].add(new Pair(even(b), cost));
    adj[odd(b)].add(new Pair(even(a), cost));
    adj[even(b)].add(new Pair(odd(a), cost));
}
 
// Function calculates shortest
// distance to all nodes from
// "source" using Dijkstra
// Shortest Path Algorithm
// and returns shortest distance
// to "destination"
static int dijkstra(int source, int destination)
{
     
    // Priority Queue/min-heap to store
    // and process (distance, node)
    PriorityQueue<Pair> pq = new PriorityQueue<>();
 
    // Pushing source node to
    // priority queue and dist from
    // source to source is set to 0
    pq.add(new Pair(0, even(source)));
    dist[even(source)] = 0;
 
    while (!pq.isEmpty())
    {
         
        // U is the node at top
        // of the priority queue
        // note that pq.top().first
        // refers to the Distance
        // and pq.top().second
        // will refer to the Node
        int u = pq.poll().second;
 
        // Exploring all neighbours
        // of node u
        for(Pair p : adj[u])
        {
             
            // v is neighbour node of u and
            // c is the cost/weight of edge (u, v)
            int v = p.first;
            int c = p.second;
 
            // Relaxation: checking if there
            // is a shorter path to v via u
            if (dist[u] + c < dist[v])
            {
                 
                // Updating distance of v
                dist[v] = dist[u] + c;
                pq.add(new Pair(dist[v], v));
            }
        }
    }
     
    // Returning shortest
    // distance to "destination"
    return dist[even(destination)];
}
 
// Driver code
public static void main(String[] args)
{
    for(int i = 0; i < MAXX * 10 + 3; i++)
    {
        adj[i] = new ArrayList<Pair>();
    }
 
    Arrays.fill(dist, INF);
 
    // n = number of Nodes,
    // m = number of Edges
    int n = 5, m = 6;
    addEdge(1, 2, 1);
    addEdge(2, 3, 2);
    addEdge(2, 5, 15);
    addEdge(3, 5, 1);
    addEdge(3, 4, 4);
    addEdge(5, 4, 3);
 
    int source = 1;
    int destination = n;
    int ans = dijkstra(source, destination);
 
    // If ans is INF: There is no
    // even length path from source
    // to destination else path
    // exists and we print the
    // shortest distance
    if (ans == INF)
        System.out.println("-1");
    else
        System.out.println(ans);
}
}
 
// This code is contributed by sanjeev2552


Python3




# Python3 program for the above approach
import heapq as hq
 
MAXX = 10000
INF = 1e9
 
# Adjacency List: to represent graph
adj = [[] for _ in range(MAXX * 10 + 3)]
 
# Distance Array: to store shortest
# distance to every node
dist = [INF] * (MAXX * 10 + 3)
 
# returns value which will
# represent even_x
def even(x):
    return x * 10 + 2
 
 
# returns value which will
# represent odd_x
def odd(x):
    return x * 10 + 1
 
 
# converting edge (a->b) to 2
# different edges i.e. (a->b)
# converts to (1). even_a -> odd_b
# (2). odd_a -> even_b
# since, graph is undirected, so we
# push them in reverse order too
# hence, 4 append operations are
# there.
def addEdge(a, b, cost):
    adj[even(a)].append((odd(b), cost))
    adj[odd(a)].append((even(b), cost))
    adj[odd(b)].append((even(a), cost))
    adj[even(b)].append((odd(a), cost))
 
 
# Function calculates shortest
# distance to all nodes from
# "source" using Dijkstra
# Shortest Path Algorithm
# and returns shortest distance
# to "destination"
def dijkstra(source, destination):
 
    # Priority Queue/min-heap
    # to store and process
    # (distance, node)
    pq = []
 
    # pushing source node to
    # priority queue and dist from
    # source to source is set to 0
    hq.heappush(pq, (0, even(source)))
    dist[even(source)] = 0
 
    while pq:
 
        # U is the node at top
        # of the priority queue
        # note that pq.top()[1]
        # refers to the Distance
        # and pq.top()[1]
        # will refer to the Node
        u = hq.heappop(pq)[1]
 
        # exploring all neighbours
        # of node u
        # v is neighbour node of u
        # and c is the cost/weight
        # of edge (u, v)
        for v, c in adj[u]:
 
            # relaxation: checking if there
            # is a shorter path to v via u
            if dist[u] + c < dist[v]:
 
                # updating distance of v
                dist[v] = dist[u] + c
                hq.heappush(pq, (dist[v], v))
 
    # returning shortest
    # distance to "destination"
    return dist[even(destination)]
 
 
# Driver function
if __name__ == "__main__":
    # n = number of Nodes,
    # m = number of Edges
    n = 5
    m = 6
    addEdge(1, 2, 1)
    addEdge(2, 3, 2)
    addEdge(2, 5, 15)
    addEdge(3, 5, 1)
    addEdge(3, 4, 4)
    addEdge(5, 4, 3)
 
    source = 1
    destination = n
    ans = dijkstra(source, destination)
 
    # if ans is INF: There is no
    # even length path from source
    # to destination else path
    # exists and we print
    # shortest distance
    if ans == INF:
        print(-1)
    else:
        print(ans)


C#




using System;
using System.Collections.Generic;
 
class GFG
{
     
 // converting edge (a->b) to 2 different edges i.e. (a->b) converts to
    // (1). even_a -> odd_b (2). odd_a -> even_b
    // since, graph is undirected, so we push them in reverse order too
    // hence, 4 push_back operations are there.
    static void addEdge(int a, int b, int cost, List<List<Tuple<int, int>>> adj)
    {
        int evenA = even(a);
        int oddB = odd(b);
        int oddA = odd(a);
        int evenB = even(b);
 
        adj[evenA].Add(Tuple.Create(oddB, cost));
        adj[oddA].Add(Tuple.Create(evenB, cost));
        adj[oddB].Add(Tuple.Create(evenA, cost));
        adj[evenB].Add(Tuple.Create(oddA, cost));
    }
 // returns value which will represent even_x
    static int even(int x)
    {
        return x * 10 + 2;
    }
 // returns value which will represent odd_x
    static int odd(int x)
    {
        return x * 10 + 1;
    }
 
    static int Dijkstra(int source, int destination, List<List<Tuple<int, int>>> adj, List<int> dist)
    {
         // Priority Queue/min-heap to store and process (distance, node)
        var pq = new SortedSet<Tuple<int, int>>(Comparer<Tuple<int, int>>.Create((a, b) => a.Item1.CompareTo(b.Item1)));
 
        pq.Add(Tuple.Create(0, even(source)));
        dist[even(source)] = 0;
 
        while (pq.Count > 0)
        {
             // U is the node at top of the priority queue
            // note that pq.Keys[0].Item1 refers to the Distance
            // and pq.Values[0] will refer to the Node
            var u = pq.Min;
            pq.Remove(u);
 // exploring all neighbours of node u
            foreach (var p in adj[u.Item2])
            {
                int v = p.Item1;
                int c = p.Item2;
// v is neighbour node of u and c is the cost/weight of edge (u, v)
                // relaxation: checking if there is a shorter path to v via u
                if (dist[u.Item2] + c < dist[v])
                {
                    dist[v] = dist[u.Item2] + c;
                    pq.Add(Tuple.Create(dist[v], v));
                }
            }
        }
 // returning shortest distance to "destination"
        return dist[even(destination)];
    }
    //Driver code
    static void Main(string[] args)
    {// n = number of Nodes, m = number of Edges
        int n = 5, m = 6;
        var adj = new List<List<Tuple<int, int>>>();
        var dist = new List<int>();
        for (int i = 0; i < n * 10 + 3; i++)
        {
            adj.Add(new List<Tuple<int, int>>());
            dist.Add(int.MaxValue);
        }
 
        addEdge(1, 2, 1, adj);
        addEdge(2, 3, 2, adj);
        addEdge(2, 5, 15, adj);
        addEdge(3, 5, 1, adj);
        addEdge(3, 4, 4, adj);
        addEdge(5, 4, 3, adj);
 
        int source = 1;
        int destination = n;
        int ans = Dijkstra(source, destination, adj, dist);
 
        if (ans == int.MaxValue)
        {
            Console.WriteLine("-1");
        }
        else
        {
            Console.WriteLine(ans);
        }
    }
}


Javascript




class PriorityQueue {
  constructor() {
    this.items = [];
  }
 
  enqueue(item, priority) {
    this.items.push({ item, priority });
    this.items.sort((a, b) => a.priority - b.priority);
  }
 
  dequeue() {
    if (this.isEmpty()) {
      return null;
    }
    return this.items.shift().item;
  }
 
  isEmpty() {
    return this.items.length === 0;
  }
}
 
const MAXX = 10000;
const INF = 1e9;
 
// Adjacency List: to represent graph
const adj = new Array(MAXX * 10 + 3).fill(null).map(() => []);
 
// Distance Array: to store shortest
// distance to every node
const dist = new Array(MAXX * 10 + 3).fill(INF);
 
// returns value which will
// represent even_x
function even(x) {
  return x * 10 + 2;
}
 
// returns value which will
// represent odd_x
function odd(x) {
  return x * 10 + 1;
}
 
// converting edge (a->b) to 2
// different edges i.e. (a->b)
// converts to (1). even_a -> odd_b
// (2). odd_a -> even_b
// since, graph is undirected, so we
// push them in reverse order too
// hence, 4 push_back operations are
// there.
function addEdge(a, b, cost) {
  adj[even(a)].push([odd(b), cost]);
  adj[odd(a)].push([even(b), cost]);
  adj[odd(b)].push([even(a), cost]);
  adj[even(b)].push([odd(a), cost]);
}
 
// Function calculates shortest
// distance to all nodes from
// "source" using Dijkstra
// Shortest Path Algorithm
// and returns shortest distance
// to "destination"
function dijkstra(source, destination) {
  /* Priority Queue/min-heap
  to store and process
  (distance, node) */
  const pq = new PriorityQueue();
 
  // pushing source node to
  // priority queue and dist from
  // source to source is set to 0
  pq.enqueue(even(source), 0);
  dist[even(source)] = 0;
 
  while (!pq.isEmpty()) {
    // U is the node at top
    // of the priority queue
    // note that pq.top().priority
    // refers to the Distance
    // and pq.top().item
    // will refer to the Node
    const u = pq.dequeue();
 
    // exploring all neighbours
    // of node u
    for (const [v, c] of adj[u]) {
      // relaxation: checking if there
      // is a shorter path to v via u
      if (dist[u] + c < dist[v]) {
        // updating distance of v
        dist[v] = dist[u] + c;
        pq.enqueue(v, dist[v]);
      }
    }
  }
 
  // returning shortest
  // distance to "destination"
  return dist[even(destination)];
}
// Driver function
 
  // n = number of Nodes,
  // m = number of Edges
  const n = 5, m = 6;
  addEdge(1, 2, 1);
  addEdge(2, 3, 2);
  addEdge(2, 5, 15);
  addEdge(3, 5, 1);
  addEdge(3, 4, 4);
  addEdge(5, 4, 3);
 
  const source = 1;
  const destination = n;
  const ans = dijkstra(source, destination);
 
  // if ans is INF: There is no
  // even length path from source
  // to destination else path
  // exists and we print the
  // shortest distance
  if (ans == Infinity)
    console.log(-1)
    else
    console.log(ans)


Output: 

10

 

Time Complexity: (E * log(V))
Auxiliary Space: O(V + E)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads