- Design and Analysis of Algorithms
- Home
- Basics of Algorithms
- DAA - Introduction to Algorithms
- DAA - Analysis of Algorithms
- DAA - Methodology of Analysis
- DAA - Asymptotic Notations & Apriori Analysis
- DAA - Time Complexity
- DAA - Master's Theorem
- DAA - Space Complexities
- Divide & Conquer
- DAA - Divide & Conquer Algorithm
- DAA - Max-Min Problem
- DAA - Merge Sort Algorithm
- DAA - Strassen's Matrix Multiplication
- DAA - Karatsuba Algorithm
- DAA - Towers of Hanoi
- Greedy Algorithms
- DAA - Greedy Algorithms
- DAA - Travelling Salesman Problem
- DAA - Prim's Minimal Spanning Tree
- DAA - Kruskal's Minimal Spanning Tree
- DAA - Dijkstra's Shortest Path Algorithm
- DAA - Map Colouring Algorithm
- DAA - Fractional Knapsack
- DAA - Job Sequencing with Deadline
- DAA - Optimal Merge Pattern
- Dynamic Programming
- DAA - Dynamic Programming
- DAA - Matrix Chain Multiplication
- DAA - Floyd Warshall Algorithm
- DAA - 0-1 Knapsack Problem
- DAA - Longest Common Subsequence Algorithm
- DAA - Travelling Salesman Problem using Dynamic Programming
- Randomized Algorithms
- DAA - Randomized Algorithms
- DAA - Randomized Quick Sort Algorithm
- DAA - Karger's Minimum Cut Algorithm
- DAA - Fisher-Yates Shuffle Algorithm
- Approximation Algorithms
- DAA - Approximation Algorithms
- DAA - Vertex Cover Problem
- DAA - Set Cover Problem
- DAA - Travelling Salesperson Approximation Algorithm
- Sorting Techniques
- DAA - Bubble Sort Algorithm
- DAA - Insertion Sort Algorithm
- DAA - Selection Sort Algorithm
- DAA - Shell Sort Algorithm
- DAA - Heap Sort Algorithm
- DAA - Bucket Sort Algorithm
- DAA - Counting Sort Algorithm
- DAA - Radix Sort Algorithm
- DAA - Quick Sort Algorithm
- Searching Techniques
- DAA - Searching Techniques Introduction
- DAA - Linear Search
- DAA - Binary Search
- DAA - Interpolation Search
- DAA - Jump Search
- DAA - Exponential Search
- DAA - Fibonacci Search
- DAA - Sublist Search
- DAA - Hash Table
- Graph Theory
- DAA - Shortest Paths
- DAA - Multistage Graph
- DAA - Optimal Cost Binary Search Trees
- Heap Algorithms
- DAA - Binary Heap
- DAA - Insert Method
- DAA - Heapify Method
- DAA - Extract Method
- Complexity Theory
- DAA - Deterministic vs. Nondeterministic Computations
- DAA - Max Cliques
- DAA - Vertex Cover
- DAA - P and NP Class
- DAA - Cook's Theorem
- DAA - NP Hard & NP-Complete Classes
- DAA - Hill Climbing Algorithm
- DAA Useful Resources
- DAA - Quick Guide
- DAA - Useful Resources
- DAA - Discussion
Multistage Graph
Multistage Graph
A multistage graph G = (V, E) is a directed graph where vertices are partitioned into k (where k > 1) number of disjoint subsets S = {s1,s2,…,sk} such that edge (u, v) is in E, then u Є si and v Є s1 + 1 for some subsets in the partition and |s1| = |sk| = 1.
The vertex s Є s1 is called the source and the vertex t Є sk is called sink.
G is usually assumed to be a weighted graph. In this graph, cost of an edge (i, j) is represented by c(i, j). Hence, the cost of path from source s to sink t is the sum of costs of each edges in this path.
The multistage graph problem is finding the path with minimum cost from source s to sink t.
Example
Consider the following example to understand the concept of multistage graph.
According to the formula, we have to calculate the cost (i, j) using the following steps
Step 1: Cost (K-2, j)
In this step, three nodes (node 4, 5. 6) are selected as j. Hence, we have three options to choose the minimum cost at this step.
Cost(3, 4) = min {c(4, 7) + Cost(7, 9),c(4, 8) + Cost(8, 9)} = 7
Cost(3, 5) = min {c(5, 7) + Cost(7, 9),c(5, 8) + Cost(8, 9)} = 5
Cost(3, 6) = min {c(6, 7) + Cost(7, 9),c(6, 8) + Cost(8, 9)} = 5
Step 2: Cost (K-3, j)
Two nodes are selected as j because at stage k - 3 = 2 there are two nodes, 2 and 3. So, the value i = 2 and j = 2 and 3.
Cost(2, 2) = min {c(2, 4) + Cost(4, 8) + Cost(8, 9),c(2, 6) +
Cost(6, 8) + Cost(8, 9)} = 8
Cost(2, 3) = {c(3, 4) + Cost(4, 8) + Cost(8, 9), c(3, 5) + Cost(5, 8)+ Cost(8, 9), c(3, 6) + Cost(6, 8) + Cost(8, 9)} = 10
Step 3: Cost (K-4, j)
Cost (1, 1) = {c(1, 2) + Cost(2, 6) + Cost(6, 8) + Cost(8, 9), c(1, 3) + Cost(3, 5) + Cost(5, 8) + Cost(8, 9))} = 12
c(1, 3) + Cost(3, 6) + Cost(6, 8 + Cost(8, 9))} = 13
Hence, the path having the minimum cost is 1→ 3→ 5→ 8→ 9.
#include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <limits.h> // Function to find the minimum cost path in the multistage graph typedef struct { int *path; int length; } Result; Result multistage_graph(int graph[][2], int num_edges, int num_vertices, int stages[][3], int num_stages) { // Initialize the lists to store the minimum costs and the next vertex in the path for each vertex int *min_costs = (int *)malloc(num_vertices * sizeof(int)); int *next_vertex = (int *)malloc(num_vertices * sizeof(int)); for (int i = 0; i < num_vertices; i++) { min_costs[i] = INT_MAX; next_vertex[i] = -1; } // Initialize the minimum cost for the sink vertex to 0 min_costs[num_vertices - 1] = 0; // Traverse the graph in reverse order starting from the second-last stage for (int i = num_stages - 2; i >= 0; i--) { for (int j = 0; j < num_vertices; j++) { if (stages[i][0] == j || stages[i][1] == j || stages[i][2] == j) { for (int k = 0; k < num_edges; k++) { if (graph[k][0] == j) { int neighbor = graph[k][1]; int cost = graph[k][2] + min_costs[neighbor]; if (cost < min_costs[j]) { // Update the minimum cost and next vertex for the current vertex min_costs[j] = cost; next_vertex[j] = neighbor; } } } } } } // Reconstruct the minimum cost path from source to sink int *path = (int *)malloc(num_vertices * sizeof(int)); int current_vertex = 0; // Start from the source vertex int path_length = 0; while (current_vertex != -1) { path[path_length++] = current_vertex; current_vertex = next_vertex[current_vertex]; } // Free the dynamically allocated memory for min_costs and next_vertex free(min_costs); free(next_vertex); // Store the result in a Result structure Result result; result.path = path; result.length = path_length; return result; } int main() { // Define the multistage graph represented as an adjacency list int graph[][2] = { {0, 1}, {0, 2}, {1, 3}, {1, 4}, {2, 3}, {2, 4}, {3, 5}, {4, 5}, {5, 6}, {6, 7}, {7, 8} }; int num_edges = sizeof(graph) / sizeof(graph[0]); // Define the stages of the multistage graph int stages[][3] = { {8}, // Sink stage {6, 7}, // Stage K-1 {3, 4, 5}, // Stage K-2 {1, 2} // Source stage }; int num_stages = sizeof(stages) / sizeof(stages[0]); int num_vertices = 9; // Total number of vertices in the graph // Find the minimum cost path and cost using the multistage_graph function Result result = multistage_graph(graph, num_edges, num_vertices, stages, num_stages); // Print the result printf("Minimum cost path: "); for (int i = 0; i < result.length; i++) { printf("%d ", result.path[i]); } printf("\nMinimum cost: %d\n", result.path[result.length - 1]); // Free the dynamically allocated memory for the path free(result.path); return 0; }
Output
Minimum cost path: 0 2 Minimum cost: 2
#include <iostream> #include <vector> #include <unordered_map> #include <limits> using namespace std; // Function to find the minimum cost path in the multistage graph pair<vector<int>, int> multistage_graph(unordered_map<int, unordered_map<int, int>>& graph, vector<vector<int>>& stages) { int num_stages = stages.size(); int num_vertices = graph.size(); // Initialize the lists to store the minimum costs and the next vertex in the path for each vertex vector<int> min_costs(num_vertices, numeric_limits<int>::max()); vector<int> next_vertex(num_vertices, -1); // Initialize the minimum cost for the sink vertex to 0 min_costs[num_vertices - 1] = 0; // Traverse the graph in reverse order starting from the second-last stage for (int i = num_stages - 2; i >= 0; i--) { for (int vertex : stages[i]) { for (auto neighbor : graph[vertex]) { int cost = neighbor.second + min_costs[neighbor.first]; if (cost < min_costs[vertex]) { // Update the minimum cost and next vertex for the current vertex min_costs[vertex] = cost; next_vertex[vertex] = neighbor.first; } } } } // Reconstruct the minimum cost path from source to sink vector<int> path; int current_vertex = 0; // Start from the source vertex while (current_vertex != -1) { path.push_back(current_vertex); current_vertex = next_vertex[current_vertex]; } // Return the path and the minimum cost as a pair return std::make_pair(path, min_costs[0]); } int main() { // Define the multistage graph represented as an adjacency map unordered_map<int, unordered_map<int, int>> graph = { {0, {{1, 2}, {2, 3}}}, {1, {{3, 5}, {4, 2}}}, {2, {{3, 4}, {4, 1}}}, {3, {{5, 6}}}, {4, {{5, 3}}}, {5, {{6, 1}}}, {6, {{7, 1}}}, {7, {{8, 1}}}, {8, {}} }; // Define the stages of the multistage graph vector<vector<int>> stages = { {8}, // Sink stage {6, 7}, // Stage K-1 {3, 4, 5}, // Stage K-2 {1, 2} // Source stage }; // Find the minimum cost path and cost using the multistage_graph function auto result = multistage_graph(graph, stages); // Print the result cout << "Minimum cost path: "; for (int vertex : result.first) { cout << vertex << " "; } cout << std::endl; cout << "Minimum cost: " << result.second << endl; return 0; }
Output
Minimum cost path: 0 Minimum cost: 2147483647
import java.util.*; public class Main { // Function to find the minimum cost path in the multistage graph static class Result { List<Integer> path; int cost; Result(List<Integer> path, int cost) { this.path = path; this.cost = cost; } } static Result multistage_graph(HashMap<Integer, HashMap<Integer, Integer>> graph, List<List<Integer>> stages) { int num_stages = stages.size(); int num_vertices = graph.size(); // Initialize the lists to store the minimum costs and the next vertex in the path for each vertex List<Integer> min_costs = new ArrayList<>(Collections.nCopies(num_vertices, Integer.MAX_VALUE)); List<Integer> next_vertex = new ArrayList<>(Collections.nCopies(num_vertices, -1)); // Initialize the minimum cost for the sink vertex to 0 min_costs.set(num_vertices - 1, 0); // Traverse the graph in reverse order starting from the second-last stage for (int i = num_stages - 2; i >= 0; i--) { for (int vertex : stages.get(i)) { for (Map.Entry<Integer, Integer> neighbor : graph.get(vertex).entrySet()) { int cost = neighbor.getValue() + min_costs.get(neighbor.getKey()); if (cost < min_costs.get(vertex)) { // Update the minimum cost and next vertex for the current vertex min_costs.set(vertex, cost); next_vertex.set(vertex, neighbor.getKey()); } } } } // Reconstruct the minimum cost path from source to sink List<Integer> path = new ArrayList<>(); int current_vertex = 0; // Start from the source vertex while (current_vertex != -1) { path.add(current_vertex); current_vertex = next_vertex.get(current_vertex); } // Return the path and the minimum cost as a Result object return new Result(path, min_costs.get(0)); } public static void main(String[] args) { // Define the multistage graph represented as an adjacency map HashMap<Integer, HashMap<Integer, Integer>> graph = new HashMap<>(); graph.put(0, new HashMap<>()); graph.get(0).put(1, 2); graph.get(0).put(2, 3); graph.put(1, new HashMap<>()); graph.get(1).put(3, 5); graph.get(1).put(4, 2); graph.put(2, new HashMap<>()); graph.get(2).put(3, 4); graph.get(2).put(4, 1); graph.put(3, new HashMap<>()); graph.get(3).put(5, 6); graph.put(4, new HashMap<>()); graph.get(4).put(5, 3); graph.put(5, new HashMap<>()); graph.get(5).put(6, 1); graph.put(6, new HashMap<>()); graph.get(6).put(7, 1); graph.put(7, new HashMap<>()); graph.get(7).put(8, 1); graph.put(8, new HashMap<>()); // Define the stages of the multistage graph List<List<Integer>> stages = new ArrayList<>(); stages.add(Collections.singletonList(8)); // Sink stage stages.add(Arrays.asList(6, 7)); // Stage K-1 stages.add(Arrays.asList(3, 4, 5)); // Stage K-2 stages.add(Arrays.asList(1, 2)); // Source stage // Find the minimum cost path and cost using the multistage_graph function Result result = multistage_graph(graph, stages); // Print the result System.out.print("Minimum cost path: "); for (int vertex : result.path) { System.out.print(vertex + " \n"); } System.out.println(); System.out.println("Minimum cost: " + result.cost); } }
Output
Minimum cost path: 0 Minimum cost: 2147483647s
def multistage_graph(graph, stages): num_stages = len(stages) num_vertices = len(graph) # Create a list to store the minimum costs for each vertex min_costs = [float('inf')] * num_vertices # Create a list to store the next vertex in the path for each vertex next_vertex = [None] * num_vertices # Initialize the minimum cost for the sink vertex min_costs[-1] = 0 # Traverse the graph in reverse order for i in range(num_stages - 2, -1, -1): for vertex in stages[i]: # Calculate the minimum cost and next vertex for the current vertex for neighbor in graph[vertex]: cost = graph[vertex][neighbor] + min_costs[neighbor] if cost < min_costs[vertex]: min_costs[vertex] = cost next_vertex[vertex] = neighbor # Reconstruct the minimum cost path path = [] current_vertex = 0 # Start from the source vertex while current_vertex is not None: path.append(current_vertex) current_vertex = next_vertex[current_vertex] return path, min_costs[0] # Example usage: if __name__ == "__main__": # The multistage graph represented as an adjacency dictionary graph = { 0: {1: 2, 2: 3}, 1: {3: 5, 4: 2}, 2: {3: 4, 4: 1}, 3: {5: 6}, 4: {5: 3}, 5: {6: 1}, 6: {7: 1}, 7: {8: 1}, 8: {} } # Define the stages of the multistage graph stages = [ [8], # Sink stage [6, 7], # Stage K-1 [3, 4, 5], # Stage K-2 [1, 2] # Source stage ] path, min_cost = multistage_graph(graph, stages) print("Minimum cost path:", path) print("Minimum cost:", min_cost)
Output
Minimum cost path: [0] Minimum cost: inf