|
| 1 | +# Hamiltonian Cycle Detection (Backtracking) |
| 2 | +# |
| 3 | +# The Hamiltonian Cycle problem determines whether there exists a cycle |
| 4 | +# in a graph that visits each vertex exactly once and returns to the start. |
| 5 | +# It is an NP-complete problem. |
| 6 | +# |
| 7 | +# This implementation uses backtracking to explore possible paths. |
| 8 | +# |
| 9 | +# Time Complexity: O(N!) |
| 10 | +# Space Complexity: O(N) |
| 11 | +# |
| 12 | +# Input: adjacency matrix (square matrix where adj[i][j] = 1 if edge exists) |
| 13 | +# Output: list containing: |
| 14 | +# - has_cycle: TRUE/FALSE |
| 15 | +# - cycle: list of vertices forming the Hamiltonian cycle (if found) |
| 16 | +# |
| 17 | +# Example usage at the end of this file. |
| 18 | + |
| 19 | +hamiltonian_cycle <- function(graph) { |
| 20 | + num_vertices <- nrow(graph) |
| 21 | + path <- rep(-1, num_vertices) |
| 22 | + |
| 23 | + # Start at vertex 1 (can be any vertex) |
| 24 | + path[1] <- 1 |
| 25 | + |
| 26 | + # Helper function to check if vertex v can be added at position pos |
| 27 | + is_safe <- function(v, graph, path, pos) { |
| 28 | + # Check if current vertex is adjacent to previous vertex |
| 29 | + if (graph[path[pos - 1], v] == 0) return(FALSE) |
| 30 | + |
| 31 | + # Check if vertex is already in the path |
| 32 | + if (v %in% path[1:(pos - 1)]) return(FALSE) |
| 33 | + |
| 34 | + return(TRUE) |
| 35 | + } |
| 36 | + |
| 37 | + # Recursive utility to build Hamiltonian cycle |
| 38 | + ham_cycle_util <- function(graph, path, pos) { |
| 39 | + if (pos == num_vertices + 1) { |
| 40 | + # If last vertex connects to the first → cycle found |
| 41 | + if (graph[path[num_vertices], path[1]] == 1) { |
| 42 | + return(TRUE) |
| 43 | + } else { |
| 44 | + return(FALSE) |
| 45 | + } |
| 46 | + } |
| 47 | + |
| 48 | + # Try adding each vertex as next candidate |
| 49 | + for (v in 2:num_vertices) { |
| 50 | + if (is_safe(v, graph, path, pos)) { |
| 51 | + path[pos] <- v |
| 52 | + if (ham_cycle_util(graph, path, pos + 1)) return(TRUE) |
| 53 | + # Backtrack |
| 54 | + path[pos] <- -1 |
| 55 | + } |
| 56 | + } |
| 57 | + return(FALSE) |
| 58 | + } |
| 59 | + |
| 60 | + # Start backtracking from vertex 1 |
| 61 | + if (ham_cycle_util(graph, path, 2)) { |
| 62 | + path <- c(path, path[1]) # complete the cycle |
| 63 | + return(list(has_cycle = TRUE, cycle = path)) |
| 64 | + } else { |
| 65 | + return(list(has_cycle = FALSE, cycle = NULL)) |
| 66 | + } |
| 67 | +} |
| 68 | + |
| 69 | +# ============================ |
| 70 | +# Example Usage and Test |
| 71 | +# ============================ |
| 72 | + |
| 73 | +cat("=== Hamiltonian Cycle Detection ===\n") |
| 74 | + |
| 75 | +# Example graph (Adjacency Matrix) |
| 76 | +# Graph: |
| 77 | +# 1 - 2 - 3 |
| 78 | +# | | | |
| 79 | +# 4 - 5 - 6 |
| 80 | +# This graph contains a Hamiltonian cycle |
| 81 | +ham_graph <- matrix( |
| 82 | + c(0,1,0,1,0,0, |
| 83 | + 1,0,1,1,1,0, |
| 84 | + 0,1,0,0,1,1, |
| 85 | + 1,1,0,0,1,0, |
| 86 | + 0,1,1,1,0,1, |
| 87 | + 0,0,1,0,1,0), |
| 88 | + nrow = 6, byrow = TRUE |
| 89 | +) |
| 90 | + |
| 91 | +cat("Adjacency Matrix:\n") |
| 92 | +print(ham_graph) |
| 93 | + |
| 94 | +cat("\nRunning Hamiltonian Cycle detection...\n") |
| 95 | +result <- hamiltonian_cycle(ham_graph) |
| 96 | + |
| 97 | +if (result$has_cycle) { |
| 98 | + cat("Hamiltonian Cycle found:\n") |
| 99 | + cat("Cycle:", paste(result$cycle, collapse = " -> "), "\n") |
| 100 | +} else { |
| 101 | + cat("No Hamiltonian Cycle exists in this graph.\n") |
| 102 | +} |
0 commit comments