using System.Collections.Generic;
public class DroneDelivery
public static int FindMinimumDeliveryTime(
List<Tuple<int, int, int>> flightPaths,
HashSet<int> processingCenters,
if (flightPaths == null || processingCenters == null)
throw new ArgumentNullException("Flight paths or processing centers cannot be null.");
throw new ArgumentException("Processing delay cannot be negative.");
Dictionary<int, List<Tuple<int, int>>> graph = new Dictionary<int, List<Tuple<int, int>>>();
foreach (var path in flightPaths)
if (!graph.ContainsKey(path.Item1))
graph[path.Item1] = new List<Tuple<int, int>>();
graph[path.Item1].Add(Tuple.Create(path.Item2, path.Item3));
Dictionary<int, int> distances = new Dictionary<int, int>();
foreach (var hub in graph.Keys)
distances[hub] = int.MaxValue;
PriorityQueue<int, int> priorityQueue = new PriorityQueue<int, int>();
priorityQueue.Enqueue(source, 0);
while (priorityQueue.Count > 0)
int currentHub = priorityQueue.Dequeue();
if (!graph.ContainsKey(currentHub))
foreach (var neighbor in graph[currentHub])
int nextHub = neighbor.Item1;
int travelTime = neighbor.Item2;
int delay = (processingCenters.Contains(currentHub) && currentHub != source && currentHub != destination)
int newDist = distances[currentHub] + travelTime + delay;
if (!distances.ContainsKey(nextHub))
distances[nextHub] = int.MaxValue;
if (newDist < distances[nextHub])
distances[nextHub] = newDist;
priorityQueue.Enqueue(nextHub, newDist);
return distances[destination] == int.MaxValue ? -1 : distances[destination];
public class DroneDeliveryTests
List<Tuple<int, int, int>> flightPaths = new List<Tuple<int, int, int>>
HashSet<int> processingCenters = new HashSet<int> { 1, 3 };
Assert.That(DroneDelivery.FindMinimumDeliveryTime(flightPaths, processingCenters, source, destination, processingDelay), Is.EqualTo(18));
public void NoProcessingCentersTest()
List<Tuple<int, int, int>> flightPaths = new List<Tuple<int, int, int>>
HashSet<int> processingCenters = new HashSet<int>();
Assert.That(DroneDelivery.FindMinimumDeliveryTime(flightPaths, processingCenters, source, destination, processingDelay), Is.EqualTo(15));
public void AllHubsProcessingCentersTest()
List<Tuple<int, int, int>> flightPaths = new List<Tuple<int, int, int>>
HashSet<int> processingCenters = new HashSet<int> { 0, 1, 2 };
Assert.That(DroneDelivery.FindMinimumDeliveryTime(flightPaths, processingCenters, source, destination, processingDelay), Is.EqualTo(18));
List<Tuple<int, int, int>> flightPaths = new List<Tuple<int, int, int>>
HashSet<int> processingCenters = new HashSet<int>();
Assert.That(DroneDelivery.FindMinimumDeliveryTime(flightPaths, processingCenters, source, destination, processingDelay), Is.EqualTo(-1));
public void SameSourceDestinationTest()
List<Tuple<int, int, int>> flightPaths = new List<Tuple<int, int, int>>
HashSet<int> processingCenters = new HashSet<int>();
Assert.That(DroneDelivery.FindMinimumDeliveryTime(flightPaths, processingCenters, source, destination, processingDelay), Is.EqualTo(0));
public void LargeGraphTest()
List<Tuple<int, int, int>> flightPaths = new List<Tuple<int, int, int>>();
for (int i = 0; i < 100; i++)
flightPaths.Add(Tuple.Create(i, i + 1, 1));
HashSet<int> processingCenters = new HashSet<int>();
Assert.That(DroneDelivery.FindMinimumDeliveryTime(flightPaths, processingCenters, source, destination, processingDelay), Is.EqualTo(100));
public void ZeroFlightTimesTest()
List<Tuple<int, int, int>> flightPaths = new List<Tuple<int, int, int>>
HashSet<int> processingCenters = new HashSet<int> { 1 };
Assert.That(DroneDelivery.FindMinimumDeliveryTime(flightPaths, processingCenters, source, destination, processingDelay), Is.EqualTo(3));
public void EmptyFlightPathsTest()
List<Tuple<int, int, int>> flightPaths = new List<Tuple<int, int, int>>();
HashSet<int> processingCenters = new HashSet<int>();
Assert.That(DroneDelivery.FindMinimumDeliveryTime(flightPaths, processingCenters, source, destination, processingDelay), Is.EqualTo(-1));
public void NegativeProcessingDelayTest()
List<Tuple<int, int, int>> flightPaths = new List<Tuple<int, int, int>>
HashSet<int> processingCenters = new HashSet<int>();
int processingDelay = -3;
Assert.Throws<ArgumentException>(() => DroneDelivery.FindMinimumDeliveryTime(flightPaths, processingCenters, source, destination, processingDelay));
public void NullFlightPathsTest()
List<Tuple<int, int, int>> flightPaths = null;
HashSet<int> processingCenters = new HashSet<int>();
Assert.Throws<ArgumentNullException>(() => DroneDelivery.FindMinimumDeliveryTime(flightPaths, processingCenters, source, destination, processingDelay));
public void NullProcessingCentersTest()
List<Tuple<int, int, int>> flightPaths = new List<Tuple<int, int, int>>
HashSet<int> processingCenters = null;
Assert.Throws<ArgumentNullException>(() => DroneDelivery.FindMinimumDeliveryTime(flightPaths, processingCenters, source, destination, processingDelay));
public class PriorityQueue<T, TPriority> where TPriority : IComparable<TPriority>
private List<(T item, TPriority priority)> _elements = new List<(T item, TPriority priority)>();
public int Count => _elements.Count;
public void Enqueue(T item, TPriority priority)
_elements.Add((item, priority));
_elements.Sort((x, y) => x.priority.CompareTo(y.priority));
if (_elements.Count == 0)
throw new InvalidOperationException("Priority queue is empty.");
T item = _elements[0].item;
public static void Main(string[] args)
var tests = new DroneDeliveryTests();
int passed = 0, failed = 0;
var testMethods = new List<Action>
tests.NoProcessingCentersTest,
tests.AllHubsProcessingCentersTest,
tests.SameSourceDestinationTest,
tests.ZeroFlightTimesTest,
tests.EmptyFlightPathsTest,
tests.NegativeProcessingDelayTest,
tests.NullFlightPathsTest,
tests.NullProcessingCentersTest
foreach (var test in testMethods)
Console.WriteLine($"{test.Method.Name}: Passed");
Console.WriteLine($"{test.Method.Name}: Failed - {ex.Message}");
Console.WriteLine($"Total tests: {passed + failed}, Passed: {passed}, Failed: {failed}");