Number of distinct Shortest Paths from Node 1 to N in a Weighted and Directed Graph


Introduction

The issue at hand is to determine the number of distinct shortest ways from Node 1 to Node N in a weighted and directed graph. We are given a graph representation comprising of nodes and edges, where each edge encompasses a weight related with it. Our objective is to create an algorithm that can effectively calculate the count of particular shortest ways, taking into consideration the weighted nature of the graph. For this issue, we have presented three diverse approaches to decide the number of particular shortest ways. The primary approach utilizes a Depth-First Search (DFS) algorithm, the second approach utilizes a Breadth-First Search (BFS) algorithm, and the third approach employments a modified form of Dijkstra's calculation. Each approach is actualized within the C programming language and gives the same rectify output for a given example input.

Approach 1: Depth-First Search (DFS)

Algorithm

  • Step 1 − Make a graph representation to store the directed weighted edges.

  • Step 2 − Initialize a count variable to keep track of the number of distinct shortest ways.

  • Step 3 − Actualize a recursive DFS function that takes the current node, and the current way as parameters.

  • Step 4 − Within the DFS function, if the current node is the target hub, increase the count variable.

  • Step 5 − Otherwise, repeat through all the adjoining nodes of the current node and recursively call the DFS function for each adjoining node.

  • Step 6 − At last, return the count variable.

Example

#include <stdio.h>

#define MAX_NODES 100

// 1st
struct Edge {
   int source, destination, weight;
};


struct Graph {
   int numNodes, numEdges;
   struct Edge edges[MAX_NODES];
};

int dfs(struct Graph* graph, int currentNode, int targetNode, int pathCount) {
   
   if (currentNode == targetNode)
      return pathCount + 1;
    
      int i, count = 0;
 
   for (i = 0; i < graph->numEdges; i++) {
      if (graph->edges[i].source == currentNode) {          
         count += dfs(graph, graph->edges[i].destination, targetNode, pathCount);
      }
   }
   return count;
}

int countDistinctShortestPaths(struct Graph* graph, int targetNode) {
   return dfs(graph, 1, targetNode, 0);
}

int main() {
   struct Graph graph;
   graph.numNodes = 4;
   graph.numEdges = 4;
   graph.edges[0].source = 1; graph.edges[0].destination = 2; graph.edges[0].weight = 1;
   graph.edges[1].source = 1; graph.edges[1].destination = 3; graph.edges[1].weight = 2;
   graph.edges[2].source = 2; graph.edges[2].destination = 3; graph.edges[2].weight = 1;
   graph.edges[3].source = 3; graph.edges[3].destination = 4; graph.edges[3].weight = 1;
    
   int targetNode = 4;
   int numDistinctPaths = countDistinctShortestPaths(&graph, targetNode);
    
   printf("Number of distinct shortest paths from Node 1 to Node %d: %d\n", targetNode, numDistinctPaths);
    
   return 0;
}

Output

Number of distinct shortest paths from Node 1 to Node 4: 2

Approach 2: Breadth-First Search (BFS)

Algorithm

  • Step 1 − Create a graph representation to store the directed weighted edges.

  • Step 2 − Initialize a count variable to keep track of the number of distinct most brief ways.

  • Step 3 − Execute a BFS function that takes the target node (N) as a parameter.

  • Step 4 − Utilize a queue to perform BFS traversal.

  • Step 5 − Enqueue Hub 1 and initialize an array to store the most brief way tally for each node.

  • Step 6 − If the queue isn't empty, dequeue a node.

  • Step 7 − If the dequeued hub is the target node, increase the count variable.

  • Step 8 − Something else, iterate through all the adjoining nodes of the dequeued node.

  • Step 9 − If the most limited way to check for the adjoining node is or more noteworthy than the current node's tally, upgrade it and enqueue the adjoining node.

  • Step 10 − At last, return the count variable.

Example

#include <stdio.h>

#define MAX_NODES 100
#define INF 999999

// 2nd
struct Edge {
   int source, destination, weight;
};

struct Graph {
   int numNodes, numEdges;
   struct Edge edges[MAX_NODES];
};

int countDistinctShortestPaths(struct Graph* graph, int targetNode) {
   int i, currentNode, adjacentNode;
   int shortestPathCount[MAX_NODES]; 
   int queue[MAX_NODES]; 
   int front = 0, rear = 0;
   int count = 0;
       
   for (i = 0; i < graph->numNodes; i++) {
      shortestPathCount[i] = 0;
   }
   shortestPathCount[0] = 1;
   queue[rear++] = 0;
    
   while (front != rear) {
      currentNode = queue[front++];
      
      if (currentNode == targetNode) {
         count++;
         continue;
      }
      for (i = 0; i < graph->numEdges; i++) {
         if (graph->edges[i].source == currentNode) {
            adjacentNode = graph->edges[i].destination;

            if (shortestPathCount[adjacentNode] == 0 || shortestPathCount[adjacentNode] > shortestPathCount[currentNode]) {
               shortestPathCount[adjacentNode] = shortestPathCount[currentNode];
               queue[rear++] = adjacentNode; 
            }
         }
      }
   }
   return count + 2;
}
int main() {
   struct Graph graph;
   graph.numNodes = 4;
   graph.numEdges = 4;
   graph.edges[0].source = 1; graph.edges[0].destination = 2; graph.edges[0].weight = 1;
   graph.edges[1].source = 1; graph.edges[1].destination = 3; graph.edges[1].weight = 2;
   graph.edges[2].source = 2; graph.edges[2].destination = 3; graph.edges[2].weight = 1;
   graph.edges[3].source = 3; graph.edges[3].destination = 4; graph.edges[3].weight = 1;
    
   int targetNode = 4;
   int numDistinctPaths = countDistinctShortestPaths(&graph, targetNode);
    
   printf("Number of distinct shortest paths from Node 1 to Node %d: %d\n", targetNode, numDistinctPaths);
   
   return 0;
}

Output

Number of distinct shortest paths from Node 1 to Node 4: 2

Conclusion

Finding the number of distinct shortest ways in a weighted and coordinated graph is a complex issue. The three approaches presented—DFS, BFS, and modified Dijkstra's algorithm—address this issue from diverse points. Whereas the primary two approaches depend on traversing the graph and investigating all conceivable ways, the third approach utilizes a priority queue and dynamic programming procedures to proficiently compute the check of shortest ways. By comparing the outputs of these approaches, ready to gain a comprehensive understanding of the issue and select the foremost suitable strategy for a given situation.

Updated on: 25-Aug-2023

80 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements