#include c_err_t c_DijkstraAllPairsSP_Init(c_DijkstraAllPairsSP_t* self, c_EdgeWeightedDigraph_t* graph, c_Allocator_t* allocator) { if (!self || !graph) return C_ERR_PARAM; self->allocator = allocator ? *allocator : c_DefaultAllocator; self->V = graph->V; self->sp_matrix = NULL; if (self->V == 0) return C_SUCCESS; /* 1. Allocate an array of DijkstraSP structures */ self->sp_matrix = (c_DijkstraSP_t*)c_Allocator_Calloc( &self->allocator, self->V, sizeof(c_DijkstraSP_t) ); if (!self->sp_matrix) return C_ERR_NOMEM; /* 2. Run a full single-source Dijkstra search engine out from each vertex */ for (c_size_t v = 0; v < self->V; ++v) { c_err_t err = c_DijkstraSP_Init(&self->sp_matrix[v], graph, v, allocator); if (err != C_SUCCESS) { /* Atomic Rollback: Destroy previously allocated instances to prevent OOM memory leaks */ for (c_size_t i = 0; i < v; ++i) { c_DijkstraSP_Destroy(&self->sp_matrix[i]); } c_Allocator_Free(&self->allocator, self->sp_matrix); self->sp_matrix = NULL; self->V = 0; return err; } } return C_SUCCESS; } void c_DijkstraAllPairsSP_Destroy(c_DijkstraAllPairsSP_t* self) { if (!self) return; if (self->sp_matrix) { /* Safely deallocate every single active search instance */ for (c_size_t i = 0; i < self->V; ++i) { c_DijkstraSP_Destroy(&self->sp_matrix[i]); } c_Allocator_Free(&self->allocator, self->sp_matrix); self->sp_matrix = NULL; } self->V = 0; } c_err_t c_DijkstraAllPairsSP_Path(c_DijkstraAllPairsSP_t* self, c_size_t u, c_size_t v, c_VertexIdList_t* out_path) { if (!self || !self->sp_matrix || u >= self->V || v >= self->V || !out_path) return C_ERR_PARAM; /* Safely delegate extraction to the underlying single-source engine */ return c_DijkstraSP_PathTo(&self->sp_matrix[u], v, out_path); }