![Design and Analysis of Algorithms Tutorial](/design_and_analysis_of_algorithms/images/design-and-analysis-of-algorithms-mini-logo.jpg)
- 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.
![Multistage Graph](/design_and_analysis_of_algorithms/images/multistage_graph.jpg)
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