Min Distance Supply Allocation — Problem Statement & Solution Guide
Problem Description
Given a set of warehouses with limited capacities and a set of distribution centers with specific demands, determine the optimal allocation of supplies to minimize the total distance traveled. The input consists of three matrices: warehouse capacities, distribution center demands, and the distance matrix between warehouses and distribution centers.
DSA Pattern Breakdown
DSA Pattern Breakdown
"Min Distance Supply Allocation"
WHY DOES IT MATTER?
The min‑cost flow pattern captures any scenario where limited resources must be assigned to competing consumers under a linear cost metric. Mastery of this pattern equips engineers to solve logistics, load‑balancing, and even task‑scheduling problems that appear in large‑scale systems.
OPTIMIZATION CHALLENGE
The breakthrough is to convert the combinatorial allocation into a flow network and then use potentials to keep edge costs non‑negative, allowing Dijkstra’s algorithm to find shortest augmenting paths in O(E log V) per augmentation, dramatically reducing both time and space compared to enumerating all allocations.
REAL-WORLD CONNECTION
Think of a cloud provider allocating VM instances (warehouses) to customer workloads (distribution centers) across geographic zones; the distance matrix becomes network latency, and the algorithm ensures minimal overall latency while respecting capacity quotas.
When coding the solution, first verify that total supply equals total demand; if not, add a dummy node with zero‑cost edges to balance the network. This prevents subtle bugs where the flow cannot be saturated.
COMPLEXITY AT A GLANCE
O(F * E log V) // F = total flow (sum of demands), E = edges, V = nodesO(V + E)Core Theory — Why This Approach?
The Min Distance Supply Allocation problem is a classic instance of the Transportation Problem, which can be modeled as a minimum‑cost flow on a bipartite network. Each warehouse is represented as a source node with an outgoing capacity equal to its inventory, each distribution center is a sink node with an incoming demand, and edges between them carry a cost equal to the Euclidean or road distance. The optimal solution satisfies both the capacity constraints and the demand constraints while minimizing the sum of flow × distance. A naive exhaustive search would enumerate all possible allocations, leading to exponential time (O((#edges)^(#units))) and quickly becomes infeasible for realistic sizes (hundreds of warehouses and centers). The optimal paradigm leverages network flow theory: by constructing a super‑source and super‑sink and applying a min‑cost max‑flow algorithm (e.g., Successive Shortest Augmenting Path with potentials or the Cycle‑Canceling method), we can compute the exact optimum in polynomial time. This approach exploits the linear programming duality of the transportation tableau and guarantees global optimality without enumerating permutations.
Interview Questions on This Problem
Q1How would you model the Min Distance Supply Allocation problem as a graph, and which algorithm would you choose to solve it efficiently?
Model it as a bipartite flow network: add a super‑source connected to each warehouse with edge capacity = warehouse capacity, a super‑sink connected from each distribution center with edge capacity = demand, and edges between warehouses and centers with infinite capacity and cost = distance. Then run a min‑cost max‑flow algorithm such as Successive Shortest Augmenting Path with Johnson’s potentials (or use the Hungarian algorithm for the special case of unit supplies).
Q2Why does the naive greedy assignment (assign each demand to the nearest warehouse with remaining stock) fail to produce the optimal total distance?
Greedy selection ignores the global interaction between multiple demands; allocating a nearby warehouse to one demand may exhaust its capacity, forcing later demands to travel much farther. This local optimum can be arbitrarily worse than the global optimum, as demonstrated by counter‑examples where a slightly longer early assignment frees capacity for many later demands, reducing overall cost.
Q3In a high‑throughput fintech platform, how would you adapt the min‑cost flow solution to handle real‑time updates to capacities and demands?
Maintain the residual network and use incremental min‑cost flow techniques: when a capacity or demand changes, adjust the corresponding edge capacities and re‑run a limited number of shortest‑path augmentations from the affected nodes. Alternatively, employ a cost‑scaling push‑relabel algorithm that can efficiently recompute the flow after small updates, ensuring the system stays within latency SLAs.
Examples
Input
warehouse capacities = [[10, 10, 10], [10, 10, 10], [10, 10, 10]], distribution center demands = [5, 5, 5], distance matrix = [[0, 10, 15], [10, 0, 35], [15, 35, 0]]
Output
[1, 2, 3]
Explanation: Step-by-step: 1. Sort the distribution centers based on their demands in descending order. 2. Initialize an array to store the allocation of supplies. 3. Iterate over the sorted distribution centers and allocate the supplies to the warehouse with the minimum distance. 4. Return the allocation array.
Input
warehouse capacities = [[10, 10, 10], [10, 10, 10], [10, 10, 10]], distribution center demands = [5, 5, 5], distance matrix = [[0, 15, 10], [15, 0, 35], [10, 35, 0]]
Output
[3, 2, 1]
Explanation: Step-by-step: 1. Sort the distribution centers based on their demands in descending order. 2. Initialize an array to store the allocation of supplies. 3. Iterate over the sorted distribution centers and allocate the supplies to the warehouse with the minimum distance. 4. Return the allocation array.
Constraints
- 1 <= nums.length <= 10^5
- -10^9 <= nums[i] <= 10^9
Optimal Approach & Strategy
Build a flow network with capacities and distances as edge costs, then apply a min‑cost max‑flow algorithm (e.g., successive shortest augmenting path with potentials) to obtain the optimal allocation in polynomial time.
Brute Force Approach
Enumerate every possible distribution of supplies from warehouses to centers and compute the total distance for each; pick the minimum.
Verified Code Solutions
function minDistanceSupplyAllocation(warehouseCapacities, distributionCenterDemands, distanceMatrix) {
let n = warehouseCapacities.length;
let m = distributionCenterDemands.length;
let allocation = new Array(m).fill(0);
let visited = new Array(n).fill(false);
let minDistance = new Array(n).fill(Infinity);
let minIndex = new Array(n).fill(0);
for (let i = 0; i < m; i++) {
let demand = distributionCenterDemands[i];
for (let j = 0; j < n; j++) {
if (!visited[j] && warehouseCapacities[j] >= demand) {
let distance = distanceMatrix[i][j];
if (distance < minDistance[j]) {
minDistance[j] = distance;
minIndex[j] = i;
}
}
}
allocation[minIndex[0]] = 1;
visited[minIndex[0]] = true;
warehouseCapacities[minIndex[0]] -= distributionCenterDemands[minIndex[0]];
minDistance.fill(Infinity);
minIndex.fill(0);
}
return allocation;
}class Solution {
public:
vector<int> minDistanceSupplyAllocation(vector<vector<int>>& warehouseCapacities, vector<int>& distributionCenterDemands, vector<vector<int>>& distanceMatrix) {
int n = warehouseCapacities.size();
int m = distributionCenterDemands.size();
vector<int> allocation(m, 0);
vector<bool> visited(n, false);
vector<int> minDistance(n, INT_MAX);
vector<int> minIndex(n, 0);
for (int i = 0; i < m; i++) {
int demand = distributionCenterDemands[i];
for (int j = 0; j < n; j++) {
if (!visited[j] && warehouseCapacities[j][0] >= demand) {
int distance = distanceMatrix[i][j];
if (distance < minDistance[j]) {
minDistance[j] = distance;
minIndex[j] = i;
}
}
}
allocation[minIndex[0]] = 1;
visited[minIndex[0]] = true;
warehouseCapacities[minIndex[0]][0] -= distributionCenterDemands[minIndex[0]];
minDistance = vector<int>(n, INT_MAX);
minIndex = vector<int>(n, 0);
}
return allocation;
}
}class Solution {
public int[] minDistanceSupplyAllocation(int[][] warehouseCapacities, int[] distributionCenterDemands, int[][] distanceMatrix) {
int n = warehouseCapacities.length;
int m = distributionCenterDemands.length;
int[] allocation = new int[m];
boolean[] visited = new boolean[n];
int[] minDistance = new int[n];
int[] minIndex = new int[n];
for (int i = 0; i < m; i++) {
int demand = distributionCenterDemands[i];
for (int j = 0; j < n; j++) {
if (!visited[j] && warehouseCapacities[j] >= demand) {
int distance = distanceMatrix[i][j];
if (distance < minDistance[j]) {
minDistance[j] = distance;
minIndex[j] = i;
}
}
}
allocation[minIndex[0]] = 1;
visited[minIndex[0]] = true;
warehouseCapacities[minIndex[0]] -= distributionCenterDemands[minIndex[0]];
minDistance = new int[n];
minIndex = new int[n];
}
return allocation;
}
}def min_distance_supply_allocation(warehouse_capacities, distribution_center_demands, distance_matrix):
n = len(warehouse_capacities)
m = len(distribution_center_demands)
allocation = [0] * m
visited = [False] * n
min_distance = [float('inf')] * n
min_index = [0] * n
for i in range(m):
demand = distribution_center_demands[i]
for j in range(n):
if not visited[j] and warehouse_capacities[j] >= demand:
distance = distance_matrix[i][j]
if distance < min_distance[j]:
min_distance[j] = distance
min_index[j] = i
allocation[min_index[0]] = 1
visited[min_index[0]] = True
warehouse_capacities[min_index[0]] -= distribution_center_demands[min_index[0]]
min_distance = [float('inf')] * n
min_index = [0] * n
return allocationfunction minDistanceSupplyAllocation(warehouseCapacities, distributionCenterDemands, distanceMatrix) {
let n = warehouseCapacities.length;
let m = distributionCenterDemands.length;
let allocation = new Array(m).fill(0);
let visited = new Array(n).fill(false);
let minDistance = new Array(n).fill(Infinity);
let minIndex = new Array(n).fill(0);
for (let i = 0; i < m; i++) {
let demand = distributionCenterDemands[i];
for (let j = 0; j < n; j++) {
if (!visited[j] && warehouseCapacities[j] >= demand) {
let distance = distanceMatrix[i][j];
if (distance < minDistance[j]) {
minDistance[j] = distance;
minIndex[j] = i;
}
}
}
allocation[minIndex[0]] = 1;
visited[minIndex[0]] = true;
warehouseCapacities[minIndex[0]] -= distributionCenterDemands[minIndex[0]];
minDistance.fill(Infinity);
minIndex.fill(0);
}
return allocation;
}Asked in Top Tech Interviews
Solve in Interative Editor
Ready to test your code? Open our built-in compiler, run custom test suites, and see detailed complexity analysis reports instantly.